';
if (!empty($conf->global->ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL) && $in_bookkeeping == 'notyet') {
print '
';
}
diff --git a/htdocs/accountancy/supplier/lines.php b/htdocs/accountancy/supplier/lines.php
index b7d0a0423f3..9f769ae13b4 100644
--- a/htdocs/accountancy/supplier/lines.php
+++ b/htdocs/accountancy/supplier/lines.php
@@ -521,7 +521,7 @@ if ($result) {
}
print '';
- print '
'.$langs->trans("CompanyAddress").' ';
diff --git a/htdocs/admin/agenda_xcal.php b/htdocs/admin/agenda_xcal.php
index 0166769660a..ce36d97d06a 100644
--- a/htdocs/admin/agenda_xcal.php
+++ b/htdocs/admin/agenda_xcal.php
@@ -164,6 +164,9 @@ $urlvcal .= $urlwithroot.'/public/agenda/agendaexport.php?format=vcal'.$getentit
$message .= img_picto('', 'globe').' '.str_replace('{url}', $urlvcal, ''.$langs->trans("WebCalUrlForVCalExport", 'vcal', '').' ');
$message .= '';
$message .= ajax_autoselect('onlinepaymenturl1');
$message .= ' ';
@@ -173,6 +176,9 @@ $urlical .= $urlwithroot.'/public/agenda/agendaexport.php?format=ical&type=event
$message .= img_picto('', 'globe').' '.str_replace('{url}', $urlical, ''.$langs->trans("WebCalUrlForVCalExport", 'ical/ics', '').' ');
$message .= '';
$message .= ajax_autoselect('onlinepaymenturl2');
$message .= ' ';
@@ -182,6 +188,9 @@ $urlrss .= $urlwithroot.'/public/agenda/agendaexport.php?format=rss'.$getentity.
$message .= img_picto('', 'globe').' '.str_replace('{url}', $urlrss, ''.$langs->trans("WebCalUrlForVCalExport", 'rss', '').' ');
$message .= '';
$message .= ajax_autoselect('onlinepaymenturl3');
$message .= ' ';
diff --git a/htdocs/admin/confexped.php b/htdocs/admin/confexped.php
index b218a245c99..c2ca271e5ea 100644
--- a/htdocs/admin/confexped.php
+++ b/htdocs/admin/confexped.php
@@ -107,7 +107,7 @@ print ' '.$langs->trans("SendingsAbility").' ';
print '';
print ' ';
print '';
-print $langs->trans("Required");
+print ''.img_picto($langs->trans("Required"), 'switch_on').' ';
/*if (empty($conf->global->MAIN_SUBMODULE_EXPEDITION))
{
print ''.img_picto($langs->trans("Disabled"),'switch_off').' ';
diff --git a/htdocs/admin/delais.php b/htdocs/admin/delais.php
index 229fb3e2291..2ae77b03d07 100644
--- a/htdocs/admin/delais.php
+++ b/htdocs/admin/delais.php
@@ -222,7 +222,8 @@ if ($action == 'edit') {
print ' ';
print '';
- print ''.$langs->trans("DelaysOfToleranceBeforeWarning").' '.$langs->trans("Value").' ';
+ print ''.$langs->trans("DelaysOfToleranceBeforeWarning").' ';
+ print ''.$langs->trans("LateWarningAfter").' ';
foreach ($modules as $module => $delays) {
if (!empty($conf->$module->enabled)) {
@@ -230,7 +231,7 @@ if ($action == 'edit') {
$value = (!empty($conf->global->{$delay['code']}) ? $conf->global->{$delay['code']}:0);
print '';
print ''.img_object('', $delay['img']).' ';
- print ''.$langs->trans('Delays_'.$delay['code']).' ';
+ print ' '.$langs->trans('Delays_'.$delay['code']).' ';
print ' '.$langs->trans("days").' ';
}
}
@@ -242,10 +243,10 @@ if ($action == 'edit') {
// Show if meteo is enabled
print '';
- print ''.$langs->trans("Parameter").' '.$langs->trans("Value").' ';
+ print ''.$langs->trans("Option").' '.$langs->trans("Value").' ';
print '';
- print ''.$langs->trans("MAIN_DISABLE_METEO").' ';
+ print ' '.$langs->trans("MAIN_DISABLE_METEO").' ';
print $form->selectarray('MAIN_DISABLE_METEO', $labelmeteo, (empty($conf->global->MAIN_DISABLE_METEO) ? 0 : $conf->global->MAIN_DISABLE_METEO));
print ' ';
@@ -256,7 +257,7 @@ if ($action == 'edit') {
*/
print '';
- print ''.$langs->trans("DelaysOfToleranceBeforeWarning").' '.$langs->trans("Value").' ';
+ print ''.$langs->trans("DelaysOfToleranceBeforeWarning").' '.$langs->trans("Value").' ';
foreach ($modules as $module => $delays) {
if (!empty($conf->$module->enabled)) {
@@ -276,7 +277,7 @@ if ($action == 'edit') {
// Show if meteo is enabled
print '';
- print ''.$langs->trans("Parameter").' '.$langs->trans("Value").' ';
+ print ''.$langs->trans("Option").' '.$langs->trans("Value").' ';
print '';
print ''.$langs->trans("MAIN_DISABLE_METEO").' ';
@@ -301,7 +302,7 @@ if (empty($conf->global->MAIN_DISABLE_METEO) || $conf->global->MAIN_DISABLE_METE
} else {
$str_mode_enabled = $str_mode_percentage;
}
- print ''.$str_mode_enabled.' ';
+ print ''.$str_mode_enabled.' ';
print ' ';
print ' ';
@@ -451,8 +452,9 @@ if ($action == 'edit') {
print $form->buttonsSaveCancel("Save", '');
print '';
} else {
- print ' ';
+ print ' ';
}
// End of page
diff --git a/htdocs/admin/openinghours.php b/htdocs/admin/openinghours.php
index a0f02fe99ac..b18ebd0c05f 100644
--- a/htdocs/admin/openinghours.php
+++ b/htdocs/admin/openinghours.php
@@ -97,7 +97,7 @@ if (empty($action) || $action == 'edit' || $action == 'updateedit') {
print ' ';
print $form->textwithpicto($langs->trans("Monday"), $langs->trans("OpeningHoursFormatDesc"));
print ' ';
- print ' global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '' : ' autofocus="autofocus"').'> '."\n";
+ print ' global->MAIN_INFO_OPENINGHOURS_MONDAY) ? ' autofocus="autofocus"' : '').'>'."\n";
print '';
print $form->textwithpicto($langs->trans("Tuesday"), $langs->trans("OpeningHoursFormatDesc"));
diff --git a/htdocs/admin/pdf.php b/htdocs/admin/pdf.php
index f04bfd78abd..fd8377b0a27 100644
--- a/htdocs/admin/pdf.php
+++ b/htdocs/admin/pdf.php
@@ -249,7 +249,7 @@ print load_fiche_titre($langs->trans("PDF"), '', 'title_setup');
$head = pdf_admin_prepare_head();
-print dol_get_fiche_head($head, 'general', $langs->trans("PDF"), -1, 'pdf');
+print dol_get_fiche_head($head, 'general', '', -1, '');
print ''.$form->textwithpicto($langs->trans("PDFDesc"), $s)." \n";
print " \n";
diff --git a/htdocs/admin/pdf_other.php b/htdocs/admin/pdf_other.php
index f42c49a4bfe..72acf7fbf4f 100644
--- a/htdocs/admin/pdf_other.php
+++ b/htdocs/admin/pdf_other.php
@@ -84,7 +84,7 @@ print load_fiche_titre($langs->trans("PDF"), '', 'title_setup');
$head = pdf_admin_prepare_head();
-print dol_get_fiche_head($head, 'other', $langs->trans("other"), -1, 'pdf');
+print dol_get_fiche_head($head, 'other', '', -1, '');
$tooltiptext = '';
print ''.$form->textwithpicto($langs->trans("PDFOtherDesc"), $tooltiptext)." \n";
diff --git a/htdocs/admin/ticket.php b/htdocs/admin/ticket.php
index f4e5b4f3fad..fc8a5e8e0b9 100644
--- a/htdocs/admin/ticket.php
+++ b/htdocs/admin/ticket.php
@@ -143,6 +143,20 @@ if ($action == 'updateMask') {
}
}
+if ($action == 'setvarworkflow') {
+ $param_auto_read = GETPOST('TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND', 'alpha');
+ $res = dolibarr_set_const($db, 'TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND', $param_auto_read, 'chaine', 0, '', $conf->entity);
+ if (!($res > 0)) {
+ $error++;
+ }
+
+ $param_auto_assign = GETPOST('TICKET_AUTO_ASSIGN_USER_CREATE', 'alpha');
+ $res = dolibarr_set_const($db, 'TICKET_AUTO_ASSIGN_USER_CREATE', $param_auto_assign, 'chaine', 0, '', $conf->entity);
+ if (!($res > 0)) {
+ $error++;
+ }
+}
+
if ($action == 'setvarother') {
$param_must_exists = GETPOST('TICKET_EMAIL_MUST_EXISTS', 'alpha');
$res = dolibarr_set_const($db, 'TICKET_EMAIL_MUST_EXISTS', $param_must_exists, 'chaine', 0, '', $conf->entity);
@@ -177,12 +191,6 @@ if ($action == 'setvarother') {
if (!($res > 0)) {
$error++;
}
-
- $param_auto_assign = GETPOST('TICKET_AUTO_ASSIGN_USER_CREATE', 'alpha');
- $res = dolibarr_set_const($db, 'TICKET_AUTO_ASSIGN_USER_CREATE', $param_auto_assign, 'chaine', 0, '', $conf->entity);
- if (!($res > 0)) {
- $error++;
- }
}
@@ -467,7 +475,7 @@ print ' ';
if (!$conf->use_javascript_ajax) {
print ' \n";
+// Auto mark ticket read when created from backoffice
+print ''.$langs->trans("TicketsAutoReadTicket").' ';
+print '';
+if ($conf->use_javascript_ajax) {
+ print ajax_constantonoff('TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND');
+} else {
+ $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+ print $form->selectarray("TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND", $arrval, $conf->global->TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND);
+}
+print ' ';
+print '';
+print $form->textwithpicto('', $langs->trans("TicketsAutoReadTicketHelp"), 1, 'help');
+print ' ';
+print ' ';
+
// Auto assign ticket at user who created it
print ''.$langs->trans("TicketsAutoAssignTicket").' ';
print '';
diff --git a/htdocs/admin/translation.php b/htdocs/admin/translation.php
index 93f62337746..bb42808ebd4 100644
--- a/htdocs/admin/translation.php
+++ b/htdocs/admin/translation.php
@@ -254,6 +254,60 @@ $head = translation_prepare_head();
print dol_get_fiche_head($head, $mode, '', -1, '');
+
+$langcode = GETPOSTISSET('langcode') ? GETPOST('langcode') : $langs->defaultlang;
+
+$newlang = new Translate('', $conf);
+$newlang->setDefaultLang($langcode);
+
+$langsenfileonly = new Translate('', $conf);
+$langsenfileonly->setDefaultLang('en_US');
+
+$newlangfileonly = new Translate('', $conf);
+$newlangfileonly->setDefaultLang($langcode);
+
+$recordtoshow = array();
+
+// Search modules dirs
+$modulesdir = dolGetModulesDirs();
+
+$nbtotaloffiles = 0;
+
+// Search into dir of modules (the $modulesdir is already a list that loop on $conf->file->dol_document_root)
+$i = 0;
+foreach ($modulesdir as $keydir => $tmpsearchdir) {
+ $searchdir = $tmpsearchdir; // $searchdir can be '.../htdocs/core/modules/' or '.../htdocs/custom/mymodule/core/modules/'
+
+ // Directory of translation files
+ $dir_lang = dirname(dirname($searchdir))."/langs/".$langcode; // The 2 dirname is to go up in dir for 2 levels
+ $dir_lang_osencoded = dol_osencode($dir_lang);
+
+ $filearray = dol_dir_list($dir_lang_osencoded, 'files', 0, '', '', $sortfield, (strtolower($sortorder) == 'asc' ?SORT_ASC:SORT_DESC), 1);
+ foreach ($filearray as $file) {
+ $tmpfile = preg_replace('/.lang/i', '', basename($file['name']));
+ $moduledirname = (basename(dirname(dirname($dir_lang))));
+
+ $langkey = $tmpfile;
+ if ($i > 0) {
+ $langkey .= '@'.$moduledirname;
+ }
+ //var_dump($i.' - '.$keydir.' - '.$dir_lang_osencoded.' -> '.$moduledirname . ' / ' . $tmpfile.' -> '.$langkey);
+
+ $result = $newlang->load($langkey, 0, 0, '', 0); // Load translation files + database overwrite
+ $result = $newlangfileonly->load($langkey, 0, 0, '', 1); // Load translation files only
+ if ($result < 0) {
+ print 'Failed to load language file '.$tmpfile.' '."\n";
+ } else {
+ $nbtotaloffiles++;
+ }
+ //print 'After loading lang '.$langkey.', newlang has '.count($newlang->tab_translate).' records '."\n";
+
+ $result = $langsenfileonly->load($langkey, 0, 0, '', 1); // Load translation files only
+ }
+ $i++;
+}
+
+
if ($mode == 'overwrite') {
print ' ';
@@ -348,7 +402,14 @@ if ($mode == 'overwrite') {
if ($action == 'edit' && $obj->rowid == GETPOST('rowid', 'int')) {
print ' ';
} else {
+ //print $obj->transkey.' '.$langsenfileonly->tab_translate[$obj->transkey];
+ $titleforvalue = $langs->trans("Translation").' en_US for key '.$obj->transkey.': '.($langsenfileonly->tab_translate[$obj->transkey] ? $langsenfileonly->trans($obj->transkey) : ''.$langs->trans("None").' ');
+ /*if ($obj->lang != 'en_US') {
+ $titleforvalue .= ' '.$langs->trans("Translation").' '.$obj->lang.' '...;
+ }*/
+ print '';
print dol_escape_htmltag($obj->transvalue);
+ print ' ';
}
print ' ';
@@ -376,20 +437,6 @@ if ($mode == 'overwrite') {
}
if ($mode == 'searchkey') {
- $langcode = GETPOSTISSET('langcode') ? GETPOST('langcode') : $langs->defaultlang;
-
- $newlang = new Translate('', $conf);
- $newlang->setDefaultLang($langcode);
-
- $newlangfileonly = new Translate('', $conf);
- $newlangfileonly->setDefaultLang($langcode);
-
- $recordtoshow = array();
-
- // Search modules dirs
- $modulesdir = dolGetModulesDirs();
-
- $nbtotaloffiles = 0;
$nbempty = 0;
/*var_dump($langcode);
var_dump($transkey);
@@ -403,41 +450,10 @@ if ($mode == 'searchkey') {
if (empty($transvalue)) {
$nbempty++;
}
+
if ($action == 'search' && ($nbempty > 999)) { // 999 to disable this
setEventMessages($langs->trans("WarningAtLeastKeyOrTranslationRequired"), null, 'warnings');
} else {
- // Search into dir of modules (the $modulesdir is already a list that loop on $conf->file->dol_document_root)
- $i = 0;
- foreach ($modulesdir as $keydir => $tmpsearchdir) {
- $searchdir = $tmpsearchdir; // $searchdir can be '.../htdocs/core/modules/' or '.../htdocs/custom/mymodule/core/modules/'
-
- // Directory of translation files
- $dir_lang = dirname(dirname($searchdir))."/langs/".$langcode; // The 2 dirname is to go up in dir for 2 levels
- $dir_lang_osencoded = dol_osencode($dir_lang);
-
- $filearray = dol_dir_list($dir_lang_osencoded, 'files', 0, '', '', $sortfield, (strtolower($sortorder) == 'asc' ?SORT_ASC:SORT_DESC), 1);
- foreach ($filearray as $file) {
- $tmpfile = preg_replace('/.lang/i', '', basename($file['name']));
- $moduledirname = (basename(dirname(dirname($dir_lang))));
-
- $langkey = $tmpfile;
- if ($i > 0) {
- $langkey .= '@'.$moduledirname;
- }
- //var_dump($i.' - '.$keydir.' - '.$dir_lang_osencoded.' -> '.$moduledirname . ' / ' . $tmpfile.' -> '.$langkey);
-
- $result = $newlang->load($langkey, 0, 0, '', 0); // Load translation files + database overwrite
- $result = $newlangfileonly->load($langkey, 0, 0, '', 1); // Load translation files only
- if ($result < 0) {
- print 'Failed to load language file '.$tmpfile.' '."\n";
- } else {
- $nbtotaloffiles++;
- }
- //print 'After loading lang '.$langkey.', newlang has '.count($newlang->tab_translate).' records '."\n";
- }
- $i++;
- }
-
// Now search into translation array
foreach ($newlang->tab_translate as $key => $val) {
if ($transkey && !preg_match('/'.preg_quote($transkey, '/').'/i', $key)) {
@@ -532,8 +548,12 @@ if ($mode == 'searchkey') {
break;
}
print ''.$langcode.' '.$key.' ';
+ $titleforvalue = $langs->trans("Translation").' en_US for key '.$key.': '.($langsenfileonly->tab_translate[$key] ? $langsenfileonly->trans($key) : ''.$langs->trans("None").' ');
+ print '';
print dol_escape_htmltag($val);
- print ' ';
+ print '';
+ print ' ';
+ print '';
if (!empty($newlangfileonly->tab_translate[$key])) {
if ($val != $newlangfileonly->tab_translate[$key]) {
// retrieve rowid
diff --git a/htdocs/api/class/api.class.php b/htdocs/api/class/api.class.php
index 2a6b5f33a27..fa21c37649f 100644
--- a/htdocs/api/class/api.class.php
+++ b/htdocs/api/class/api.class.php
@@ -173,6 +173,7 @@ class DolibarrApi
unset($object->stats_mrptoproduce);
unset($object->element);
+ unset($object->element_for_permission);
unset($object->fk_element);
unset($object->table_element);
unset($object->table_element_line);
diff --git a/htdocs/api/class/api_setup.class.php b/htdocs/api/class/api_setup.class.php
index 15a29c0e18b..50c909df1fe 100644
--- a/htdocs/api/class/api_setup.class.php
+++ b/htdocs/api/class/api_setup.class.php
@@ -209,7 +209,7 @@ class Setup extends DolibarrApi
if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
- $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
+ $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
}
@@ -239,7 +239,6 @@ class Setup extends DolibarrApi
return $list;
}
-
/**
* Get the list of states/provinces.
*
@@ -252,27 +251,34 @@ class Setup extends DolibarrApi
* @param string $sortorder Sort order
* @param int $limit Number of items per page
* @param int $page Page number (starting from zero)
- * @param string $filter To filter the countries by name
+ * @param int $country To filter on country
+ * @param string $filter To filter the states by name
* @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
- * @return array List of countries
+ * @return array List of states
*
* @url GET dictionary/states
*
* @throws RestException
*/
- public function getListOfStates($sortfield = "code_departement", $sortorder = 'ASC', $limit = 100, $page = 0, $filter = '', $sqlfilters = '')
+ public function getListOfStates($sortfield = "code_departement", $sortorder = 'ASC', $limit = 100, $page = 0, $country = 0, $filter = '', $sqlfilters = '')
{
$list = array();
// Note: The filter is not applied in the SQL request because it must
// be applied to the translated names, not to the names in database.
- $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."c_departements as t";
+ $sql = "SELECT t.rowid FROM ".MAIN_DB_PREFIX."c_departements as t";
+ if ($country) {
+ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_regions as d ON t.fk_region = d.code_region";
+ }
$sql .= " WHERE 1 = 1";
+ if ($country) {
+ $sql .= " AND d.fk_pays = ".((int) $country);
+ }
// Add sql filters
if ($sqlfilters) {
$errormessage = '';
if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
- throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
+ throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
@@ -373,7 +379,7 @@ class Setup extends DolibarrApi
if ($sqlfilters) {
$errormessage = '';
if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
- throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
+ throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
@@ -665,7 +671,7 @@ class Setup extends DolibarrApi
if ($sqlfilters) {
$errormessage = '';
if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
- throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
+ throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
@@ -729,7 +735,7 @@ class Setup extends DolibarrApi
if ($sqlfilters) {
$errormessage = '';
if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
- throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
+ throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
@@ -797,7 +803,7 @@ class Setup extends DolibarrApi
if ($sqlfilters) {
$errormessage = '';
if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
- throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
+ throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
@@ -860,7 +866,7 @@ class Setup extends DolibarrApi
if ($sqlfilters) {
$errormessage = '';
if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
- throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
+ throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
@@ -933,7 +939,7 @@ class Setup extends DolibarrApi
if ($sqlfilters) {
$errormessage = '';
if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
- throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
+ throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
@@ -1004,7 +1010,7 @@ class Setup extends DolibarrApi
if ($sqlfilters) {
$errormessage = '';
if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
- throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
+ throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
@@ -1078,7 +1084,7 @@ class Setup extends DolibarrApi
if ($sqlfilters) {
$errormessage = '';
if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
- throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
+ throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
@@ -1143,9 +1149,9 @@ class Setup extends DolibarrApi
if ($sqlfilters) {
$errormessage = '';
if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
- throw new RestException(400, 'error when validating parameter sqlfilters -> '.$errormessage);
+ throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
- $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
+ $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
}
@@ -1202,9 +1208,9 @@ class Setup extends DolibarrApi
if ($sqlfilters) {
$errormessage = '';
if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
- throw new RestException(400, 'error when validating parameter sqlfilters -> '.$errormessage);
+ throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
- $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
+ $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
}
@@ -1261,7 +1267,7 @@ class Setup extends DolibarrApi
if ($sqlfilters) {
$errormessage = '';
if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
- throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
+ throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
@@ -1301,7 +1307,7 @@ class Setup extends DolibarrApi
* @param string $sortorder Sort order
* @param int $limit Number of items per page
* @param int $page Page number (starting from zero)
- * @param string $country To filter on country
+ * @param int $country To filter on country
* @param int $active Lega form is active or not {@min 0} {@max 1}
* @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
* @return array List of legal form
@@ -1310,7 +1316,7 @@ class Setup extends DolibarrApi
*
* @throws RestException
*/
- public function getListOfLegalForm($sortfield = "rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $country = '', $active = 1, $sqlfilters = '')
+ public function getListOfLegalForm($sortfield = "rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $country = 0, $active = 1, $sqlfilters = '')
{
$list = array();
@@ -1318,13 +1324,13 @@ class Setup extends DolibarrApi
$sql .= " FROM ".MAIN_DB_PREFIX."c_forme_juridique as t";
$sql .= " WHERE t.active = ".((int) $active);
if ($country) {
- $sql .= " AND t.fk_pays = '".$this->db->escape($country)."'";
+ $sql .= " AND t.fk_pays = ".((int) $country);
}
// Add sql filters
if ($sqlfilters) {
$errormessage = '';
if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
- throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
+ throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
@@ -1383,7 +1389,7 @@ class Setup extends DolibarrApi
if ($sqlfilters) {
$errormessage = '';
if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
- throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
+ throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
@@ -1449,7 +1455,7 @@ class Setup extends DolibarrApi
if ($sqlfilters) {
$errormessage = '';
if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
- throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
+ throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
@@ -1508,7 +1514,7 @@ class Setup extends DolibarrApi
if ($sqlfilters) {
$errormessage = '';
if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
- throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
+ throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
@@ -1567,7 +1573,7 @@ class Setup extends DolibarrApi
if ($sqlfilters) {
$errormessage = '';
if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
- throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
+ throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
@@ -1628,7 +1634,7 @@ class Setup extends DolibarrApi
if ($sqlfilters) {
$errormessage = '';
if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
- throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
+ throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
diff --git a/htdocs/api/index.php b/htdocs/api/index.php
index 70aeae96447..d5bc7e273e2 100644
--- a/htdocs/api/index.php
+++ b/htdocs/api/index.php
@@ -55,12 +55,27 @@ if (!empty($_SERVER['HTTP_DOLAPIENTITY'])) {
define("DOLENTITY", (int) $_SERVER['HTTP_DOLAPIENTITY']);
}
+// Response for preflight requests (used by browser when into a CORS context)
+if (!empty($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'OPTIONS' && !empty($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
+ header('Access-Control-Allow-Origin: *');
+ header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
+ header('Access-Control-Allow-Headers: Content-Type, Authorization, api_key, DOLAPIKEY');
+ http_response_code(204);
+ exit;
+}
+
// When we request url to get the json file, we accept Cross site so we can include the descriptor into an external tool.
if (preg_match('/\/explorer\/swagger\.json/', $_SERVER["PHP_SELF"])) {
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
header('Access-Control-Allow-Headers: Content-Type, Authorization, api_key, DOLAPIKEY');
}
+// When we request url to get an API, we accept Cross site so we can make js API call inside another website
+if (preg_match('/\/api\/index\.php/', $_SERVER["PHP_SELF"])) {
+ header('Access-Control-Allow-Origin: *');
+ header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
+ header('Access-Control-Allow-Headers: Content-Type, Authorization, api_key, DOLAPIKEY');
+}
$res = 0;
if (!$res && file_exists("../main.inc.php")) {
@@ -304,7 +319,7 @@ if (!empty($reg[1]) && ($reg[1] != 'explorer' || ($reg[2] != '/swagger.json' &&
foreach ($listofendpoints as $endpointrule) {
$tmparray = explode(':', $endpointrule);
- if ($classfile == $tmparray[0] && $tmparray[1] == 1) {
+ if (($classfile == $tmparray[0] || $classfile.'api' == $tmparray[0]) && $tmparray[1] == 1) {
$endpointisallowed = true;
break;
}
diff --git a/htdocs/asset/class/asset.class.php b/htdocs/asset/class/asset.class.php
index e5ec21bfa6d..916fb376526 100644
--- a/htdocs/asset/class/asset.class.php
+++ b/htdocs/asset/class/asset.class.php
@@ -305,7 +305,7 @@ class Asset extends CommonObject
*/
public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
{
- global $db, $conf, $langs;
+ global $db, $conf, $langs, $hookmanager;
global $dolibarr_main_authentication, $dolibarr_main_demo;
global $menumanager;
@@ -360,7 +360,15 @@ class Asset extends CommonObject
}
$result .= $linkend;
//if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
-
+ global $action;
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) {
+ $result = $hookmanager->resPrint;
+ } else {
+ $result .= $hookmanager->resPrint;
+ }
return $result;
}
diff --git a/htdocs/barcode/printsheet.php b/htdocs/barcode/printsheet.php
index 5128cd56164..8663d50e66a 100644
--- a/htdocs/barcode/printsheet.php
+++ b/htdocs/barcode/printsheet.php
@@ -374,24 +374,24 @@ jQuery(document).ready(function() {
';
// Checkbox to select from free text
-print ' '.$langs->trans("FillBarCodeTypeAndValueManually").' ';
+print ' '.$langs->trans("FillBarCodeTypeAndValueManually").' ';
print ' ';
if (!empty($user->rights->produit->lire) || !empty($user->rights->service->lire)) {
- print ' '.$langs->trans("FillBarCodeTypeAndValueFromProduct").' ';
+ print ' '.$langs->trans("FillBarCodeTypeAndValueFromProduct").' ';
print ' ';
print '';
$form->select_produits(GETPOST('productid', 'int'), 'productid', '', '', 0, -1, 2, '', 0, array(), 0, '1', 0, 'minwidth400imp', 1);
- print ' ';
+ print ' ';
print '
';
}
if (!empty($user->rights->societe->lire)) {
- print ' '.$langs->trans("FillBarCodeTypeAndValueFromThirdParty").' ';
+ print ' '.$langs->trans("FillBarCodeTypeAndValueFromThirdParty").' ';
print ' ';
print '';
print $form->select_company(GETPOST('socid', 'int'), 'socid', '', 'SelectThirdParty', 0, 0, array(), 0, 'minwidth300');
- print ' ';
+ print ' ';
print '
';
}
diff --git a/htdocs/bom/bom_card.php b/htdocs/bom/bom_card.php
index cbd730e5d23..f6e40b511f1 100644
--- a/htdocs/bom/bom_card.php
+++ b/htdocs/bom/bom_card.php
@@ -518,7 +518,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
// Common attributes
$keyforbreak = 'duration';
include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php';
-
+ $object->calculateCosts();
print ' '.$form->textwithpicto($langs->trans("TotalCost"), $langs->trans("BOMTotalCost")).' '.price($object->total_cost).' ';
print ''.$langs->trans("UnitCost").' '.price($object->unit_cost).' ';
diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php
index 17d17edad8d..20ff5fe27b1 100644
--- a/htdocs/bom/class/bom.class.php
+++ b/htdocs/bom/class/bom.class.php
@@ -847,7 +847,7 @@ class BOM extends CommonObject
global $action, $hookmanager;
$hookmanager->initHooks(array('bomdao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
@@ -1086,7 +1086,7 @@ class BOM extends CommonObject
if ($res>0) {
$bom_child->calculateCosts();
$line->childBom[] = $bom_child;
- $this->total_cost += $bom_child->total_cost;
+ $this->total_cost += $bom_child->total_cost * $line->qty;
} else {
$this->error = $bom_child->error;
return -2;
@@ -1521,7 +1521,7 @@ class BOMLine extends CommonObjectLine
global $action, $hookmanager;
$hookmanager->initHooks(array('bomlinedao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php
index b72ed043581..8040310ea53 100644
--- a/htdocs/bom/tpl/objectline_view.tpl.php
+++ b/htdocs/bom/tpl/objectline_view.tpl.php
@@ -180,6 +180,7 @@ if ($action == 'selectlines') {
print '';
// Select of all the sub-BOM lines
+// From this pont to the end of the file, we only take care of sub-BOM lines
$sql = 'SELECT rowid, fk_bom_child, fk_product, qty FROM '.MAIN_DB_PREFIX.'bom_bomline AS bl';
$sql.= ' WHERE fk_bom ='. (int) $tmpbom->id;
$resql = $object->db->query($sql);
@@ -191,7 +192,9 @@ if ($resql) {
$sub_bom_product->fetch($obj->fk_product);
$sub_bom = new BOM($object->db);
- $sub_bom->fetch($obj->fk_bom_child);
+ if (!empty($obj->fk_bom_child)) {
+ $sub_bom->fetch($obj->fk_bom_child);
+ }
$sub_bom_line = new BOMLine($object->db);
$sub_bom_line->fetch($obj->rowid);
@@ -233,20 +236,23 @@ if ($resql) {
// Efficiency
print ''.$sub_bom_line->efficiency.' ';
- // Cost price if it's defined
- if ($sub_bom_product->cost_price > 0) {
- print ''.price($sub_bom_product->cost_price * $line->qty).' ';
- $total_cost+= $sub_bom_product->cost_price * $line->qty;
+ if (!empty($sub_bom->id)) {
+ $sub_bom->calculateCosts();
+ print ''.price($sub_bom->total_cost * $sub_bom_line->qty * $line->qty).' ';
+ $total_cost+= $sub_bom->total_cost * $sub_bom_line->qty * $line->qty;
+ } elseif ($sub_bom_product->cost_price > 0) {
+ print ''.price($sub_bom_product->cost_price * $sub_bom_line->qty * $line->qty).' ';
+ $total_cost+= $sub_bom_product->cost_price * $sub_bom_line->qty * $line->qty;
} elseif ($sub_bom_product->pmp > 0) { // PMP if cost price isn't defined
- print ''.price($sub_bom_product->pmp * $line->qty).' ';
- $total_cost.= $sub_bom_product->pmp * $line->qty;
+ print ''.price($sub_bom_product->pmp * $sub_bom_line->qty * $line->qty).' ';
+ $total_cost.= $sub_bom_product->pmp * $sub_bom_line->qty * $line->qty;
} else { // Minimum purchase price if cost price and PMP aren't defined
$sql_supplier_price = 'SELECT MIN(price) AS min_price, quantity AS qty FROM '.MAIN_DB_PREFIX.'product_fournisseur_price';
$sql_supplier_price.= ' WHERE fk_product = '. (int) $sub_bom_product->id;
$resql_supplier_price = $object->db->query($sql_supplier_price);
if ($resql_supplier_price) {
$obj = $object->db->fetch_object($resql_supplier_price);
- $line_cost = $obj->min_price/$obj->qty * $sub_bom_line->qty;
+ $line_cost = $obj->min_price/$obj->qty * $sub_bom_line->qty * $line->qty;
print ''.price($line_cost).' ';
$total_cost+= $line_cost;
diff --git a/htdocs/bookmarks/class/bookmark.class.php b/htdocs/bookmarks/class/bookmark.class.php
index 9a5b3a53c20..39bb06c2ada 100644
--- a/htdocs/bookmarks/class/bookmark.class.php
+++ b/htdocs/bookmarks/class/bookmark.class.php
@@ -344,7 +344,7 @@ class Bookmark extends CommonObject
global $action, $hookmanager;
$hookmanager->initHooks(array('mybookmarkdao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
diff --git a/htdocs/categories/class/categorie.class.php b/htdocs/categories/class/categorie.class.php
index 5ffed2e5e4b..a3d2dc3e57f 100644
--- a/htdocs/categories/class/categorie.class.php
+++ b/htdocs/categories/class/categorie.class.php
@@ -10,7 +10,7 @@
* Copyright (C) 2015 Marcos García
* Copyright (C) 2015 Raphaël Doursenaud
* Copyright (C) 2016 Charlie Benke
- * Copyright (C) 2018-2019 Frédéric France
+ * Copyright (C) 2018-2022 Frédéric France
*
* 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
@@ -185,7 +185,8 @@ class Categorie extends CommonObject
'contact' => 'socpeople',
'account' => 'bank_account', // old for bank account
'project' => 'projet',
- 'warehouse'=> 'entrepot'
+ 'warehouse'=> 'entrepot',
+ 'knowledgemanagement' => 'knowledgemanagement_knowledgerecord'
);
/**
@@ -1612,7 +1613,7 @@ class Categorie extends CommonObject
*/
public function getNomUrl($withpicto = 0, $option = '', $maxlength = 0, $moreparam = '')
{
- global $langs;
+ global $langs, $hookmanager;
$result = '';
$label = $langs->trans("ShowCategory").': '.($this->ref ? $this->ref : $this->label);
@@ -1640,6 +1641,15 @@ class Categorie extends CommonObject
if ($withpicto != 2) {
$result .= $link.dol_trunc(($this->ref ? $this->ref : $this->label), $maxlength).$linkend;
}
+ global $action;
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) {
+ $result = $hookmanager->resPrint;
+ } else {
+ $result .= $hookmanager->resPrint;
+ }
return $result;
}
diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php
index 627c2f0ce51..4a00894d26b 100644
--- a/htdocs/comm/action/card.php
+++ b/htdocs/comm/action/card.php
@@ -76,11 +76,14 @@ if ($complete == 'na' || $complete == -2) {
}
if ($fulldayevent) {
- $datep = dol_mktime('00', '00', 0, GETPOST("apmonth", 'int'), GETPOST("apday", 'int'), GETPOST("apyear", 'int'));
- $datef = dol_mktime('23', '59', '59', GETPOST("p2month", 'int'), GETPOST("p2day", 'int'), GETPOST("p2year", 'int'));
+ $tzforfullday = getDolGlobalString('MAIN_STORE_FULL_EVENT_IN_GMT');
+ // For "full day" events, we must store date in GMT (It must be viewed as same moment everywhere)
+ $datep = dol_mktime('00', '00', 0, GETPOST("apmonth", 'int'), GETPOST("apday", 'int'), GETPOST("apyear", 'int'), $tzforfullday ? $tzforfullday : 'tzuserrel');
+ $datef = dol_mktime('23', '59', '59', GETPOST("p2month", 'int'), GETPOST("p2day", 'int'), GETPOST("p2year", 'int'), $tzforfullday ? $tzforfullday : 'tzuserrel');
+ //print $db->idate($datep); exit;
} else {
- $datep = dol_mktime($aphour, $apmin, 0, GETPOST("apmonth", 'int'), GETPOST("apday", 'int'), GETPOST("apyear", 'int'));
- $datef = dol_mktime($p2hour, $p2min, '59', GETPOST("p2month", 'int'), GETPOST("p2day", 'int'), GETPOST("p2year", 'int'));
+ $datep = dol_mktime($aphour, $apmin, 0, GETPOST("apmonth", 'int'), GETPOST("apday", 'int'), GETPOST("apyear", 'int'), 'tzuserrel');
+ $datef = dol_mktime($p2hour, $p2min, '59', GETPOST("p2month", 'int'), GETPOST("p2day", 'int'), GETPOST("p2year", 'int'), 'tzuserrel');
}
// Security check
@@ -252,8 +255,15 @@ if (empty($reshook) && $action == 'add') {
$percentage = in_array(GETPOST('status'), array(-1, 100)) ? GETPOST('status') : (in_array($complete, array(-1, 100)) ? $complete : GETPOST("percentage", 'int')); // If status is -1 or 100, percentage is not defined and we must use status
// Clean parameters
- $datep = dol_mktime($fulldayevent ? '00' : GETPOST("aphour", 'int'), $fulldayevent ? '00' : GETPOST("apmin", 'int'), $fulldayevent ? '00' : GETPOST("apsec", 'int'), GETPOST("apmonth", 'int'), GETPOST("apday", 'int'), GETPOST("apyear", 'int'), 'tzuser');
- $datef = dol_mktime($fulldayevent ? '23' : GETPOST("p2hour", 'int'), $fulldayevent ? '59' : GETPOST("p2min", 'int'), $fulldayevent ? '59' : GETPOST("apsec", 'int'), GETPOST("p2month", 'int'), GETPOST("p2day", 'int'), GETPOST("p2year", 'int'), 'tzuser');
+ if ($fulldayevent) {
+ $tzforfullday = getDolGlobalString('MAIN_STORE_FULL_EVENT_IN_GMT');
+ // For "full day" events, we must store date in GMT (It must be viewed as same moment everywhere)
+ $datep = dol_mktime($fulldayevent ? '00' : GETPOST("aphour", 'int'), $fulldayevent ? '00' : GETPOST("apmin", 'int'), $fulldayevent ? '00' : GETPOST("apsec", 'int'), GETPOST("apmonth", 'int'), GETPOST("apday", 'int'), GETPOST("apyear", 'int'), $tzforfullday ? $tzforfullday : 'tzuser');
+ $datef = dol_mktime($fulldayevent ? '23' : GETPOST("p2hour", 'int'), $fulldayevent ? '59' : GETPOST("p2min", 'int'), $fulldayevent ? '59' : GETPOST("apsec", 'int'), GETPOST("p2month", 'int'), GETPOST("p2day", 'int'), GETPOST("p2year", 'int'), $tzforfullday ? $tzforfullday : 'tzuser');
+ } else {
+ $datep = dol_mktime($fulldayevent ? '00' : GETPOST("aphour", 'int'), $fulldayevent ? '00' : GETPOST("apmin", 'int'), $fulldayevent ? '00' : GETPOST("apsec", 'int'), GETPOST("apmonth", 'int'), GETPOST("apday", 'int'), GETPOST("apyear", 'int'), 'tzuser');
+ $datef = dol_mktime($fulldayevent ? '23' : GETPOST("p2hour", 'int'), $fulldayevent ? '59' : GETPOST("p2min", 'int'), $fulldayevent ? '59' : GETPOST("apsec", 'int'), GETPOST("p2month", 'int'), GETPOST("p2day", 'int'), GETPOST("p2year", 'int'), 'tzuser');
+ }
// Check parameters
if (!$datef && $percentage == 100) {
@@ -513,8 +523,16 @@ if (empty($reshook) && $action == 'update') {
$object->fetch_userassigned();
$object->oldcopy = clone $object;
- $datep = dol_mktime($fulldayevent ? '00' : $aphour, $fulldayevent ? '00' : $apmin, 0, GETPOST("apmonth", 'int'), GETPOST("apday", 'int'), GETPOST("apyear", 'int'), 'tzuser');
- $datef = dol_mktime($fulldayevent ? '23' : $p2hour, $fulldayevent ? '59' : $p2min, $fulldayevent ? '59' : '0', GETPOST("p2month", 'int'), GETPOST("p2day", 'int'), GETPOST("p2year", 'int'), 'tzuser');
+ // Clean parameters
+ if ($fulldayevent) {
+ $tzforfullday = getDolGlobalString('MAIN_STORE_FULL_EVENT_IN_GMT');
+ // For "full day" events, we must store date in GMT (It must be viewed as same moment everywhere)
+ $datep = dol_mktime($fulldayevent ? '00' : GETPOST("aphour", 'int'), $fulldayevent ? '00' : GETPOST("apmin", 'int'), $fulldayevent ? '00' : GETPOST("apsec", 'int'), GETPOST("apmonth", 'int'), GETPOST("apday", 'int'), GETPOST("apyear", 'int'), $tzforfullday ? $tzforfullday : 'tzuser');
+ $datef = dol_mktime($fulldayevent ? '23' : GETPOST("p2hour", 'int'), $fulldayevent ? '59' : GETPOST("p2min", 'int'), $fulldayevent ? '59' : GETPOST("apsec", 'int'), GETPOST("p2month", 'int'), GETPOST("p2day", 'int'), GETPOST("p2year", 'int'), $tzforfullday ? $tzforfullday : 'tzuser');
+ } else {
+ $datep = dol_mktime($fulldayevent ? '00' : GETPOST("aphour", 'int'), $fulldayevent ? '00' : GETPOST("apmin", 'int'), $fulldayevent ? '00' : GETPOST("apsec", 'int'), GETPOST("apmonth", 'int'), GETPOST("apday", 'int'), GETPOST("apyear", 'int'), 'tzuser');
+ $datef = dol_mktime($fulldayevent ? '23' : GETPOST("p2hour", 'int'), $fulldayevent ? '59' : GETPOST("p2min", 'int'), $fulldayevent ? '59' : GETPOST("apsec", 'int'), GETPOST("p2month", 'int'), GETPOST("p2day", 'int'), GETPOST("p2year", 'int'), 'tzuser');
+ }
$object->type_id = dol_getIdFromCode($db, GETPOST("actioncode", 'aZ09'), 'c_actioncomm');
$object->label = GETPOST("label", "alphanohtml");
@@ -1005,11 +1023,11 @@ if ($action == 'create') {
$datep = ($datep ? $datep : (is_null($object->datep) ? '' : $object->datep));
if (GETPOST('datep', 'int', 1)) {
- $datep = dol_stringtotime(GETPOST('datep', 'int', 1), 0);
+ $datep = dol_stringtotime(GETPOST('datep', 'int', 1), 'tzuser');
}
$datef = ($datef ? $datef : $object->datef);
if (GETPOST('datef', 'int', 1)) {
- $datef = dol_stringtotime(GETPOST('datef', 'int', 1), 0);
+ $datef = dol_stringtotime(GETPOST('datef', 'int', 1), 'tzuser');
}
if (empty($datef) && !empty($datep)) {
if (GETPOST("actioncode", 'aZ09') == 'AC_RDV' || empty($conf->global->AGENDA_USE_EVENT_TYPE_DEFAULT)) {
@@ -1024,16 +1042,16 @@ if ($action == 'create') {
print ''.$langs->trans("DateActionEnd").' ';
print '';
if (GETPOST("afaire") == 1) {
- print $form->selectDate($datep, 'ap', 1, 1, 0, "action", 1, 2, 0, 'fulldaystart'); // Empty value not allowed for start date and hours if "todo"
+ print $form->selectDate($datep, 'ap', 1, 1, 0, "action", 1, 2, 0, 'fulldaystart', '', '', '', 1, '', '', 'tzuserrel'); // Empty value not allowed for start date and hours if "todo"
} else {
- print $form->selectDate($datep, 'ap', 1, 1, 1, "action", 1, 2, 0, 'fulldaystart');
+ print $form->selectDate($datep, 'ap', 1, 1, 1, "action", 1, 2, 0, 'fulldaystart', '', '', '', 1, '', '', 'tzuserrel');
}
print ' - ';
//print ' - ';
if (GETPOST("afaire") == 1) {
- print $form->selectDate($datef, 'p2', 1, 1, 1, "action", 1, 0, 0, 'fulldayend');
+ print $form->selectDate($datef, 'p2', 1, 1, 1, "action", 1, 0, 0, 'fulldayend', '', '', '', 1, '', '', 'tzuserrel');
} else {
- print $form->selectDate($datef, 'p2', 1, 1, 1, "action", 1, 0, 0, 'fulldayend');
+ print $form->selectDate($datef, 'p2', 1, 1, 1, "action", 1, 0, 0, 'fulldayend', '', '', '', 1, '', '', 'tzuserrel');
}
print ' ';
@@ -1518,20 +1536,21 @@ if ($id > 0) {
// Date start - end
print ''.$langs->trans("DateActionStart").' - '.$langs->trans("DateActionEnd").' ';
+ $tzforfullday = getDolGlobalString('MAIN_STORE_FULL_EVENT_IN_GMT');
if (GETPOST("afaire") == 1) {
- print $form->selectDate($datep ? $datep : $object->datep, 'ap', 1, 1, 0, "action", 1, 1, 0, 'fulldaystart', '', '', '', 1, '', '', 'tzuser');
+ print $form->selectDate($datep ? $datep : $object->datep, 'ap', 1, 1, 0, "action", 1, 1, 0, 'fulldaystart', '', '', '', 1, '', '', $object->fulldayevent ? ($tzforfullday ? $tzforfullday : 'tzuser') : 'tzuser');
} elseif (GETPOST("afaire") == 2) {
- print $form->selectDate($datep ? $datep : $object->datep, 'ap', 1, 1, 1, "action", 1, 1, 0, 'fulldaystart', '', '', '', 1, '', '', 'tzuser');
+ print $form->selectDate($datep ? $datep : $object->datep, 'ap', 1, 1, 1, "action", 1, 1, 0, 'fulldaystart', '', '', '', 1, '', '', $object->fulldayevent ? ($tzforfullday ? $tzforfullday : 'tzuser') : 'tzuser');
} else {
- print $form->selectDate($datep ? $datep : $object->datep, 'ap', 1, 1, 1, "action", 1, 1, 0, 'fulldaystart', '', '', '', 1, '', '', 'tzuser');
+ print $form->selectDate($datep ? $datep : $object->datep, 'ap', 1, 1, 1, "action", 1, 1, 0, 'fulldaystart', '', '', '', 1, '', '', $object->fulldayevent ? ($tzforfullday ? $tzforfullday : 'tzuser') : 'tzuser');
}
print ' - ';
if (GETPOST("afaire") == 1) {
- print $form->selectDate($datef ? $datef : $object->datef, 'p2', 1, 1, 1, "action", 1, 1, 0, 'fulldayend', '', '', '', 1, '', '', 'tzuser');
+ print $form->selectDate($datef ? $datef : $object->datef, 'p2', 1, 1, 1, "action", 1, 1, 0, 'fulldayend', '', '', '', 1, '', '', $object->fulldayevent ? ($tzforfullday ? $tzforfullday : 'tzuser') : 'tzuser');
} elseif (GETPOST("afaire") == 2) {
- print $form->selectDate($datef ? $datef : $object->datef, 'p2', 1, 1, 1, "action", 1, 1, 0, 'fulldayend', '', '', '', 1, '', '', 'tzuser');
+ print $form->selectDate($datef ? $datef : $object->datef, 'p2', 1, 1, 1, "action", 1, 1, 0, 'fulldayend', '', '', '', 1, '', '', $object->fulldayevent ? ($tzforfullday ? $tzforfullday : 'tzuser') : 'tzuser');
} else {
- print $form->selectDate($datef ? $datef : $object->datef, 'p2', 1, 1, 1, "action", 1, 1, 0, 'fulldayend', '', '', '', 1, '', '', 'tzuser');
+ print $form->selectDate($datef ? $datef : $object->datef, 'p2', 1, 1, 1, "action", 1, 1, 0, 'fulldayend', '', '', '', 1, '', '', $object->fulldayevent ? ($tzforfullday ? $tzforfullday : 'tzuser') : 'tzuser');
}
print ' ';
@@ -1972,7 +1991,8 @@ if ($id > 0) {
if (empty($object->fulldayevent)) {
print dol_print_date($object->datep, 'dayhour', 'tzuser');
} else {
- print dol_print_date($object->datep, 'day', 'tzuser');
+ $tzforfullday = getDolGlobalString('MAIN_STORE_FULL_EVENT_IN_GMT');
+ print dol_print_date($object->datep, 'day', ($tzforfullday ? $tzforfullday : 'tzuser'));
}
if ($object->percentage == 0 && $object->datep && $object->datep < ($now - $delay_warning)) {
print img_warning($langs->trans("Late"));
@@ -1985,7 +2005,8 @@ if ($id > 0) {
if (empty($object->fulldayevent)) {
print dol_print_date($object->datef, 'dayhour', 'tzuser');
} else {
- print dol_print_date($object->datef, 'day', 'tzuser');
+ $tzforfullday = getDolGlobalString('MAIN_STORE_FULL_EVENT_IN_GMT');
+ print dol_print_date($object->datef, 'day', ($tzforfullday ? $tzforfullday : 'tzuser'));
}
if ($object->percentage > 0 && $object->percentage < 100 && $object->datef && $object->datef < ($now - $delay_warning)) {
print img_warning($langs->trans("Late"));
diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php
index 19273648827..a5b4f1d8ce9 100644
--- a/htdocs/comm/action/class/actioncomm.class.php
+++ b/htdocs/comm/action/class/actioncomm.class.php
@@ -1669,7 +1669,7 @@ class ActionComm extends CommonObject
global $action;
$hookmanager->initHooks(array('actiondao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
@@ -1955,14 +1955,14 @@ class ActionComm extends CommonObject
$event = array();
$event['uid'] = 'dolibarragenda-'.$this->db->database_name.'-'.$obj->id."@".$_SERVER["SERVER_NAME"];
$event['type'] = $type;
+
$datestart = $this->db->jdate($obj->datep) - (empty($conf->global->AGENDA_EXPORT_FIX_TZ) ? 0 : ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600));
// fix for -> Warning: A non-numeric value encountered
if (is_numeric($this->db->jdate($obj->datep2))) {
- $dateend = $this->db->jdate($obj->datep2)
- - (empty($conf->global->AGENDA_EXPORT_FIX_TZ) ? 0 : ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600));
+ $dateend = $this->db->jdate($obj->datep2) - (empty($conf->global->AGENDA_EXPORT_FIX_TZ) ? 0 : ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600));
} else {
- // use start date as fall-back to avoid import erros on empty end date
+ // use start date as fall-back to avoid pb with empty end date on ICS readers
$dateend = $datestart;
}
diff --git a/htdocs/comm/action/document.php b/htdocs/comm/action/document.php
index c69d396cf26..3de00e9cb6f 100644
--- a/htdocs/comm/action/document.php
+++ b/htdocs/comm/action/document.php
@@ -201,7 +201,8 @@ if ($object->id > 0) {
if (empty($object->fulldayevent)) {
print dol_print_date($object->datep, 'dayhour', 'tzuser');
} else {
- print dol_print_date($object->datep, 'day', 'tzuser');
+ $tzforfullday = getDolGlobalString('MAIN_STORE_FULL_EVENT_IN_GMT');
+ print dol_print_date($object->datep, 'day', ($tzforfullday ? $tzforfullday : 'tzuser'));
}
if ($object->percentage == 0 && $object->datep && $object->datep < ($now - $delay_warning)) {
print img_warning($langs->trans("Late"));
@@ -214,7 +215,8 @@ if ($object->id > 0) {
if (empty($object->fulldayevent)) {
print dol_print_date($object->datef, 'dayhour', 'tzuser');
} else {
- print dol_print_date($object->datef, 'day', 'tzuser');
+ $tzforfullday = getDolGlobalString('MAIN_STORE_FULL_EVENT_IN_GMT');
+ print dol_print_date($object->datef, 'day', ($tzforfullday ? $tzforfullday : 'tzuser'));
}
if ($object->percentage > 0 && $object->percentage < 100 && $object->datef && $object->datef < ($now - $delay_warning)) {
print img_warning($langs->trans("Late"));
diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php
index d3538c6a2c9..e8060bc314d 100644
--- a/htdocs/comm/action/index.php
+++ b/htdocs/comm/action/index.php
@@ -545,7 +545,8 @@ if ($user->rights->agenda->myactions->create || $user->rights->agenda->allaction
$newparam .= '&month='.((int) $month).'&year='.((int) $tmpforcreatebutton['year']).'&mode='.urlencode($mode);
//$param='month='.$monthshown.'&year='.$year;
- $hourminsec = '100000';
+ $hourminsec = dol_print_date(dol_mktime(10, 0, 0, 1, 1, 1970, 'gmt'), '%H', 'gmt').'0000'; // Set $hourminsec to '100000' to auto set hour to 10:00 at creation
+
$newcardbutton .= dolGetButtonTitle($langs->trans("AddAction"), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/comm/action/card.php?action=create&datep='.sprintf("%04d%02d%02d", $tmpforcreatebutton['year'], $tmpforcreatebutton['mon'], $tmpforcreatebutton['mday']).$hourminsec.'&backtopage='.urlencode($_SERVER["PHP_SELF"].($newparam ? '?'.$newparam : '')));
}
@@ -808,11 +809,21 @@ if ($resql) {
$event->id = $obj->id;
$event->ref = $event->id;
- $event->datep = $db->jdate($obj->datep); // datep and datef are GMT date. Example: 1970-01-01 01:00:00, jdate will return 0 if TZ of PHP server is Europe/Berlin
- $event->datef = $db->jdate($obj->datep2);
+ $event->fulldayevent = $obj->fulldayevent;
+
+ // event->datep and event->datef must be GMT date.
+ if ($event->fulldayevent) {
+ $tzforfullday = getDolGlobalString('MAIN_STORE_FULL_EVENT_IN_GMT');
+ $event->datep = $db->jdate($obj->datep, $tzforfullday ? 'tzuser' : 'tzserver'); // If saved in $tzforfullday = gmt, we must invert date to be in user tz
+ $event->datef = $db->jdate($obj->datep2, $tzforfullday ? 'tzuser' : 'tzserver');
+ } else {
+ // Example: $obj->datep = '1970-01-01 01:00:00', jdate will return 0 if TZ of PHP server is Europe/Berlin (+1)
+ $event->datep = $db->jdate($obj->datep, 'tzserver');
+ $event->datef = $db->jdate($obj->datep2, 'tzserver');
+ }
//$event->datep_formated_gmt = dol_print_date($event->datep, 'dayhour', 'gmt');
- //var_dump($obj->datep);
- //var_dump($event->datep);
+ //var_dump($obj->id.' '.$obj->datep.' '.dol_print_date($obj->datep, 'dayhour', 'gmt'));
+ //var_dump($obj->id.' '.$event->datep.' '.dol_print_date($event->datep, 'dayhour', 'gmt'));
$event->type_code = $obj->type_code;
$event->type_label = $obj->type_label;
@@ -829,7 +840,6 @@ if ($resql) {
$event->fetch_userassigned(); // This load $event->userassigned
$event->priority = $obj->priority;
- $event->fulldayevent = $obj->fulldayevent;
$event->location = $obj->location;
$event->transparency = $obj->transparency;
$event->fk_element = $obj->fk_element;
@@ -865,25 +875,43 @@ if ($resql) {
$annee = dol_print_date($daycursor, '%Y', 'tzuserrel');
$mois = dol_print_date($daycursor, '%m', 'tzuserrel');
$jour = dol_print_date($daycursor, '%d', 'tzuserrel');
+
+ $daycursorend = $event->date_end_in_calendar;
+ $anneeend = dol_print_date($daycursorend, '%Y', 'tzuserrel');
+ $moisend = dol_print_date($daycursorend, '%m', 'tzuserrel');
+ $jourend = dol_print_date($daycursorend, '%d', 'tzuserrel');
+
//var_dump(dol_print_date($event->date_start_in_calendar, 'dayhour', 'gmt')); // Hour at greenwich
//var_dump($annee.'-'.$mois.'-'.$jour);
+ //print 'annee='.$annee.' mois='.$mois.' jour='.$jour.' ';
// Loop on each day covered by action to prepare an index to show on calendar
$loop = true; $j = 0;
- $daykey = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt');
+ $daykey = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt'); // $mois, $jour, $annee has been set for user tz
+ $daykeyend = dol_mktime(0, 0, 0, $moisend, $jourend, $anneeend, 'gmt'); // $moisend, $jourend, $anneeend has been set for user tz
+ /*
+ print 'GMT '.$event->date_start_in_calendar.' '.dol_print_date($event->date_start_in_calendar, 'dayhour', 'gmt').' ';
+ print 'TZSERVER '.$event->date_start_in_calendar.' '.dol_print_date($event->date_start_in_calendar, 'dayhour', 'tzserver').' ';
+ print 'TZUSERREL '.$event->date_start_in_calendar.' '.dol_print_date($event->date_start_in_calendar, 'dayhour', 'tzuserrel').' ';
+ print 'GMT '.$event->date_end_in_calendar.' '.dol_print_date($event->date_end_in_calendar, 'dayhour', 'gmt').' ';
+ print 'TZSERVER '.$event->date_end_in_calendar.' '.dol_print_date($event->date_end_in_calendar, 'dayhour', 'tzserver').' ';
+ print 'TZUSER '.$event->date_end_in_calendar.' '.dol_print_date($event->date_end_in_calendar, 'dayhour', 'tzuserrel').' ';
+ */
do {
//if ($event->id==408)
- //print 'daykey='.$daykey.' '.dol_print_date($daykey, 'dayhour', 'gmt').' '.$event->datep.' '.$event->datef.' ';
+ //print 'daykey='.$daykey.' daykeyend='.$daykeyend.' '.dol_print_date($daykey, 'dayhour', 'gmt').' - '.dol_print_date($event->datep, 'dayhour', 'gmt').' '.dol_print_date($event->datef, 'dayhour', 'gmt').' ';
+ //print 'daykey='.$daykey.' daykeyend='.$daykeyend.' '.dol_print_date($daykey, 'dayhour', 'tzuserrel').' - '.dol_print_date($event->datep, 'dayhour', 'tzuserrel').' '.dol_print_date($event->datef, 'dayhour', 'tzuserrel').' ';
$eventarray[$daykey][] = $event;
$j++;
$daykey += 60 * 60 * 24;
- if ($daykey > $event->date_end_in_calendar) {
+ //if ($daykey > $event->date_end_in_calendar) {
+ if ($daykey > $daykeyend) {
$loop = false;
}
} while ($loop);
-
+ //var_dump($eventarray);
//print 'Event '.$i.' id='.$event->id.' (start='.dol_print_date($event->datep).'-end='.dol_print_date($event->datef);
//print ' startincalendar='.dol_print_date($event->date_start_in_calendar).'-endincalendar='.dol_print_date($event->date_end_in_calendar).') was added in '.$j.' different index key of array ';
}
@@ -1805,12 +1833,16 @@ function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventa
$cssclass .= " unmovable";
} elseif ($event->type_code == 'ICALEVENT') {
$cssclass .= " unmovable";
- } elseif ($event->date_end_in_calendar && date('Ymd', $event->date_start_in_calendar) != date('Ymd', $event->date_end_in_calendar)) {
- $tmpyearend = date('Y', $event->date_end_in_calendar);
- $tmpmonthend = date('m', $event->date_end_in_calendar);
- $tmpdayend = date('d', $event->date_end_in_calendar);
+ } elseif ($event->date_start_in_calendar && $event->date_end_in_calendar && date('Ymd', $event->date_start_in_calendar) != date('Ymd', $event->date_end_in_calendar)) {
+ // If the event is on several days
+ $tmpyearend = dol_print_date($event->date_start_in_calendar, '%Y', 'tzuserrel');
+ $tmpmonthend = dol_print_date($event->date_start_in_calendar, '%m', 'tzuserrel');
+ $tmpdayend = dol_print_date($event->date_start_in_calendar, '%d', 'tzuserrel');
+ //var_dump($tmpyearend.' '.$tmpmonthend.' '.$tmpdayend);
if ($tmpyearend != $annee || $tmpmonthend != $mois || $tmpdayend != $jour) {
- $cssclass .= " unmovable";
+ $cssclass .= " unmovable unmovable-mustusefirstdaytodrag";
+ } else {
+ $cssclass .= ' movable cursormove';
}
} else {
if ($user->rights->agenda->allactions->create ||
diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php
index de961b5517e..e2b412e15db 100644
--- a/htdocs/comm/action/list.php
+++ b/htdocs/comm/action/list.php
@@ -693,7 +693,7 @@ $tmpforcreatebutton = dol_getdate(dol_now(), true);
$newparam = '&month='.str_pad($month, 2, "0", STR_PAD_LEFT).'&year='.$tmpforcreatebutton['year'];
//$param='month='.$monthshown.'&year='.$year;
-$hourminsec = '100000';
+$hourminsec = dol_print_date(dol_mktime(10, 0, 0, 1, 1, 1970, 'gmt'), '%H', 'gmt').'0000'; // Set $hourminsec to '100000' to auto set hour to 10:00 at creation
$url = DOL_URL_ROOT.'/comm/action/card.php?action=create';
$url .= '&datep='.sprintf("%04d%02d%02d", $tmpforcreatebutton['year'], $tmpforcreatebutton['mon'], $tmpforcreatebutton['mday']).$hourminsec;
@@ -953,7 +953,12 @@ while ($i < min($num, $limit)) {
// Start date
if (!empty($arrayfields['a.datep']['checked'])) {
print '';
- print dol_print_date($db->jdate($obj->dp), $formatToUse, 'tzuser');
+ if (empty($obj->fulldayevent)) {
+ print dol_print_date($db->jdate($obj->dp), $formatToUse, 'tzuser');
+ } else {
+ $tzforfullday = getDolGlobalString('MAIN_STORE_FULL_EVENT_IN_GMT');
+ print dol_print_date($db->jdate($obj->dp), $formatToUse, ($tzforfullday ? $tzforfullday : 'tzuser'));
+ }
$late = 0;
if ($actionstatic->hasDelay() && $actionstatic->percentage >= 0 && $actionstatic->percentage < 100 ) {
$late = 1;
@@ -967,7 +972,12 @@ while ($i < min($num, $limit)) {
// End date
if (!empty($arrayfields['a.datep2']['checked'])) {
print ' ';
- print dol_print_date($db->jdate($obj->dp2), $formatToUse, 'tzuser');
+ if (empty($obj->fulldayevent)) {
+ print dol_print_date($db->jdate($obj->dp2), $formatToUse, 'tzuser');
+ } else {
+ $tzforfullday = getDolGlobalString('MAIN_STORE_FULL_EVENT_IN_GMT');
+ print dol_print_date($db->jdate($obj->dp2), $formatToUse, ($tzforfullday ? $tzforfullday : 'tzuser'));
+ }
print ' ';
}
diff --git a/htdocs/comm/mailing/class/mailing.class.php b/htdocs/comm/mailing/class/mailing.class.php
index 8050b85f180..588faa392e3 100644
--- a/htdocs/comm/mailing/class/mailing.class.php
+++ b/htdocs/comm/mailing/class/mailing.class.php
@@ -740,7 +740,7 @@ class Mailing extends CommonObject
global $action;
$hookmanager->initHooks(array('emailingdao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php
index 746075ab51e..45a4d2fdb57 100644
--- a/htdocs/comm/propal/card.php
+++ b/htdocs/comm/propal/card.php
@@ -2543,7 +2543,7 @@ if ($action == 'create') {
if (($object->statut == Propal::STATUS_DRAFT && $object->total_ttc >= 0 && count($object->lines) > 0)
|| ($object->statut == Propal::STATUS_DRAFT && !empty($conf->global->PROPAL_ENABLE_NEGATIVE) && count($object->lines) > 0)) {
if ($usercanvalidate) {
- print 'id.'&action=validate">'.$langs->trans('Validate').' ';
+ print 'id.'&action=validate&token='.newToken().'">'.$langs->trans('Validate').' ';
} else {
print ''.$langs->trans('Validate').' ';
}
@@ -2555,7 +2555,7 @@ if ($action == 'create') {
}*/
// Edit
if ($object->statut == Propal::STATUS_VALIDATED && $usercancreate) {
- print 'id.'&action=modif">'.$langs->trans('Modify').' ';
+ print 'id.'&action=modif&token='.newToken().'">'.$langs->trans('Modify').' ';
}
// ReOpen
@@ -2578,7 +2578,7 @@ if ($action == 'create') {
// Create a sale order
if (!empty($conf->commande->enabled) && $object->statut == Propal::STATUS_SIGNED) {
if ($usercancreateorder) {
- print ''.$langs->trans("AddOrder").' ';
+ print ''.$langs->trans("AddOrder").' ';
}
}
@@ -2586,7 +2586,7 @@ if ($action == 'create') {
if (!empty($conf->global->WORKFLOW_CAN_CREATE_PURCHASE_ORDER_FROM_PROPOSAL)) {
if ($object->statut == Propal::STATUS_SIGNED && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled))) {
if ($usercancreatepurchaseorder) {
- print ''.$langs->trans("AddPurchaseOrder").' ';
+ print ''.$langs->trans("AddPurchaseOrder").' ';
}
}
}
@@ -2595,7 +2595,7 @@ if ($action == 'create') {
if (!empty($conf->service->enabled) && !empty($conf->ficheinter->enabled) && $object->statut == Propal::STATUS_SIGNED) {
if ($usercancreateintervention) {
$langs->load("interventions");
- print ''.$langs->trans("AddIntervention").' ';
+ print ''.$langs->trans("AddIntervention").' ';
}
}
@@ -2604,14 +2604,14 @@ if ($action == 'create') {
$langs->load("contracts");
if ($usercancreatecontract) {
- print ''.$langs->trans('AddContract').' ';
+ print ''.$langs->trans('AddContract').' ';
}
}
// Create an invoice and classify billed
if ($object->statut == Propal::STATUS_SIGNED && empty($conf->global->PROPOSAL_ARE_NOT_BILLABLE)) {
if (!empty($conf->facture->enabled) && $usercancreateinvoice) {
- print ''.$langs->trans("CreateBill").' ';
+ print ''.$langs->trans("CreateBill").' ';
}
$arrayofinvoiceforpropal = $object->getInvoiceArrayList();
diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php
index 1c532e26147..029706dfb5d 100644
--- a/htdocs/comm/propal/class/propal.class.php
+++ b/htdocs/comm/propal/class/propal.class.php
@@ -1248,7 +1248,7 @@ class Propal extends CommonObject
break;
}
// Defined the new fk_parent_line
- if ($result > 0 && $line->product_type == 9) {
+ if ($result > 0) {
$fk_parent_line = $result;
}
}
@@ -3569,7 +3569,7 @@ class Propal extends CommonObject
*/
public function getNomUrl($withpicto = 0, $option = '', $get_params = '', $notooltip = 0, $save_lastsearch_value = -1, $addlinktonotes = -1)
{
- global $langs, $conf, $user;
+ global $langs, $conf, $user, $hookmanager;
if (!empty($conf->dol_no_mouse_hover)) {
$notooltip = 1; // Force disable tooltips
@@ -3690,6 +3690,15 @@ class Propal extends CommonObject
}
}
+ global $action;
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) {
+ $result = $hookmanager->resPrint;
+ } else {
+ $result .= $hookmanager->resPrint;
+ }
return $result;
}
diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php
index e4cc6a37c1c..3e790bf6448 100644
--- a/htdocs/comm/propal/list.php
+++ b/htdocs/comm/propal/list.php
@@ -1486,8 +1486,11 @@ if ($resql) {
) {
$with_margin_info = true;
}
+ $total_ht = 0;
+ $total_margin = 0;
- while ($i < min($num, $limit)) {
+ $last_num = min($num, $limit);
+ while ($i < $last_num) {
$obj = $db->fetch_object($resql);
$objectstatic->id = $obj->rowid;
@@ -1541,6 +1544,8 @@ if ($resql) {
if ($with_margin_info === true) {
$objectstatic->fetch_lines();
$marginInfo = $formmargin->getMarginInfosArray($objectstatic);
+ $total_ht += $obj->total_ht;
+ $total_margin += $marginInfo['total_margin'];
}
print '';
@@ -1959,7 +1964,7 @@ if ($resql) {
if (!$i) {
$totalarray['pos'][$totalarray['nbfield']] = 'total_margin';
}
- $totalarray['val']['total_margin'] += $marginInfo['total_margin'];
+ $totalarray['val']['total_margin'] = $total_margin;
}
// Total margin rate
if (!empty($arrayfields['total_margin_rate']['checked'])) {
@@ -1974,6 +1979,16 @@ if ($resql) {
if (!$i) {
$totalarray['nbfield']++;
}
+ if (!$i) {
+ $totalarray['pos'][$totalarray['nbfield']] = 'total_mark_rate';
+ }
+ if ($i >= $last_num - 1) {
+ if (!empty($total_ht)) {
+ $totalarray['val']['total_mark_rate'] = price2num($total_margin * 100 / $total_ht, 'MT');
+ } else {
+ $totalarray['val']['total_mark_rate'] = '';
+ }
+ }
}
// Extra fields
diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php
index 958ff542fed..72851c3943a 100644
--- a/htdocs/commande/card.php
+++ b/htdocs/commande/card.php
@@ -421,7 +421,7 @@ if (empty($reshook)) {
}
// Defined the new fk_parent_line
- if ($result > 0 && $lines[$i]->product_type == 9) {
+ if ($result > 0) {
$fk_parent_line = $result;
}
}
diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php
index c315a4fcd61..a9ff2e09cf3 100644
--- a/htdocs/commande/class/commande.class.php
+++ b/htdocs/commande/class/commande.class.php
@@ -11,7 +11,7 @@
* Copyright (C) 2014-2015 Marcos García
* Copyright (C) 2018 Nicolas ZABOURI
* Copyright (C) 2016-2018 Ferran Marcet
- * Copyright (C) 2021 Frédéric France
+ * Copyright (C) 2021-2022 Frédéric France
*
* 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
@@ -1056,7 +1056,7 @@ class Commande extends CommonOrder
return -1;
}
// Defined the new fk_parent_line
- if ($result > 0 && $line->product_type == 9) {
+ if ($result > 0) {
$fk_parent_line = $result;
}
}
@@ -3663,7 +3663,7 @@ class Commande extends CommonOrder
*/
public function getNomUrl($withpicto = 0, $option = '', $max = 0, $short = 0, $notooltip = 0, $save_lastsearch_value = -1, $addlinktonotes = 0)
{
- global $conf, $langs, $user;
+ global $conf, $langs, $user, $hookmanager;
if (!empty($conf->dol_no_mouse_hover)) {
$notooltip = 1; // Force disable tooltips
@@ -3764,6 +3764,15 @@ class Commande extends CommonOrder
}
}
+ global $action;
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) {
+ $result = $hookmanager->resPrint;
+ } else {
+ $result .= $hookmanager->resPrint;
+ }
return $result;
}
diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php
index 35abd34728a..27391d7a901 100644
--- a/htdocs/commande/list.php
+++ b/htdocs/commande/list.php
@@ -1463,8 +1463,11 @@ if ($resql) {
) {
$with_margin_info = true;
}
+ $total_ht = 0;
+ $total_margin = 0;
- while ($i < min($num, $limit)) {
+ $last_num = min($num, $limit);
+ while ($i < $last_num) {
$obj = $db->fetch_object($resql);
$notshippable = 0;
@@ -1510,6 +1513,8 @@ if ($resql) {
if ($with_margin_info === true) {
$generic_commande->fetch_lines();
$marginInfo = $formmargin->getMarginInfosArray($generic_commande);
+ $total_ht += $obj->total_ht;
+ $total_margin += $marginInfo['total_margin'];
}
print '';
@@ -1879,6 +1884,16 @@ if ($resql) {
if (!$i) {
$totalarray['nbfield']++;
}
+ if (!$i) {
+ $totalarray['pos'][$totalarray['nbfield']] = 'total_mark_rate';
+ }
+ if ($i >= $last_num - 1) {
+ if (!empty($total_ht)) {
+ $totalarray['val']['total_mark_rate'] = price2num($total_margin * 100 / $total_ht, 'MT');
+ } else {
+ $totalarray['val']['total_mark_rate'] = '';
+ }
+ }
}
// Extra fields
diff --git a/htdocs/compta/ajaxpayment.php b/htdocs/compta/ajaxpayment.php
index d22e1a0182a..bdeeb072e97 100644
--- a/htdocs/compta/ajaxpayment.php
+++ b/htdocs/compta/ajaxpayment.php
@@ -56,19 +56,23 @@ $currentInvId = $_POST['imgClicked']; // from DOM elements : imgId (equals invoi
$amountPayment = $amountPayment != '' ? (is_numeric(price2num($amountPayment)) ? price2num($amountPayment) : '') : ''; // keep void if not a valid entry
// Clean checkamounts
-foreach ($amounts as $key => $value) {
- $value = price2num($value);
- $amounts[$key] = $value;
- if (empty($value)) {
- unset($amounts[$key]);
+if (is_array($amounts)) {
+ foreach ($amounts as $key => $value) {
+ $value = price2num($value);
+ $amounts[$key] = $value;
+ if (empty($value)) {
+ unset($amounts[$key]);
+ }
}
}
// Clean remains
-foreach ($remains as $key => $value) {
- $value = price2num($value);
- $remains[$key] = (($invoice_type) == 2 ?-1 : 1) * $value;
- if (empty($value)) {
- unset($remains[$key]);
+if (is_array($remains)) {
+ foreach ($remains as $key => $value) {
+ $value = price2num($value);
+ $remains[$key] = (($invoice_type) == 2 ?-1 : 1) * $value;
+ if (empty($value)) {
+ unset($remains[$key]);
+ }
}
}
diff --git a/htdocs/compta/bank/bankentries_list.php b/htdocs/compta/bank/bankentries_list.php
index 3d8e6f8bd98..e991831a6dd 100644
--- a/htdocs/compta/bank/bankentries_list.php
+++ b/htdocs/compta/bank/bankentries_list.php
@@ -544,7 +544,7 @@ if ($id > 0 || !empty($ref)) {
if ($user->rights->banque->consolidate) {
$newparam = $param;
$newparam = preg_replace('/search_conciliated=\d+/i', '', $newparam);
- $buttonreconcile = ''.$titletoconciliatemanual.' ';
+ $buttonreconcile = ''.$titletoconciliatemanual.' ';
} else {
$buttonreconcile = ''.$titletoconciliatemanual.' ';
}
@@ -554,7 +554,7 @@ if ($id > 0 || !empty($ref)) {
if ($user->rights->banque->consolidate) {
$newparam = $param;
$newparam = preg_replace('/search_conciliated=\d+/i', '', $newparam);
- $buttonreconcile .= ' '.$titletoconciliateauto.' ';
+ $buttonreconcile .= ' '.$titletoconciliateauto.' ';
} else {
$buttonreconcile .= ' '.$titletoconciliateauto.' ';
}
diff --git a/htdocs/compta/bank/card.php b/htdocs/compta/bank/card.php
index 5d2bb71109b..78940872106 100644
--- a/htdocs/compta/bank/card.php
+++ b/htdocs/compta/bank/card.php
@@ -345,7 +345,7 @@ if ($action == 'create') {
if ($conf->use_javascript_ajax) {
print "\n".''."\n";
diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php
index abd2c7dd502..732be0937d0 100644
--- a/htdocs/core/class/extrafields.class.php
+++ b/htdocs/core/class/extrafields.class.php
@@ -608,10 +608,14 @@ class ExtraFields
if ($unique) {
$sql = "ALTER TABLE ".$this->db->prefix().$table." ADD UNIQUE INDEX uk_".$table."_".$attrname." (".$attrname.")";
} else {
- $sql = "ALTER TABLE ".$this->db->prefix().$table." DROP INDEX uk_".$table."_".$attrname;
+ $sql = "ALTER TABLE ".$this->db->prefix().$table." DROP INDEX IF EXISTS uk_".$table."_".$attrname;
}
dol_syslog(get_class($this).'::update', LOG_DEBUG);
$resql = $this->db->query($sql, 1, 'dml');
+ /*if ($resql < 0) {
+ $this->error = $this->db->lasterror();
+ return -1;
+ }*/
return 1;
} else {
$this->error = $this->db->lasterror();
diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php
index 3375e9f7cc4..8f112b9aa98 100644
--- a/htdocs/core/class/html.form.class.php
+++ b/htdocs/core/class/html.form.class.php
@@ -1106,13 +1106,13 @@ class Form
}
print ''.$langs->trans("Product");
print ' '.$langs->trans("Service");
@@ -2219,9 +2219,10 @@ class Form
* 'warehouseinternal' = count products from warehouses for internal correct/transfer only
* @param array $selected_combinations Selected combinations. Format: array([attrid] => attrval, [...])
* @param string $nooutput No print, return the output into a string
+ * @param int $status_purchase Purchase status -1=Return all products, 0=Products not on purchase, 1=Products on purchase
* @return void|string
*/
- public function select_produits($selected = '', $htmlname = 'productid', $filtertype = '', $limit = 0, $price_level = 0, $status = 1, $finished = 2, $selected_input_value = '', $hidelabel = 0, $ajaxoptions = array(), $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $hidepriceinlabel = 0, $warehouseStatus = '', $selected_combinations = null, $nooutput = 0)
+ public function select_produits($selected = '', $htmlname = 'productid', $filtertype = '', $limit = 0, $price_level = 0, $status = 1, $finished = 2, $selected_input_value = '', $hidelabel = 0, $ajaxoptions = array(), $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $hidepriceinlabel = 0, $warehouseStatus = '', $selected_combinations = null, $nooutput = 0, $status_purchase = -1)
{
// phpcs:enable
global $langs, $conf;
@@ -2261,7 +2262,7 @@ class Form
}
}
// mode=1 means customers products
- $urloption = 'htmlname='.$htmlname.'&outjson=1&price_level='.$price_level.'&type='.$filtertype.'&mode=1&status='.$status.'&finished='.$finished.'&hidepriceinlabel='.$hidepriceinlabel.'&warehousestatus='.$warehouseStatus;
+ $urloption = 'htmlname='.$htmlname.'&outjson=1&price_level='.$price_level.'&type='.$filtertype.'&mode=1&status='.$status.'&status_purchase='.$status_purchase.'&finished='.$finished.'&hidepriceinlabel='.$hidepriceinlabel.'&warehousestatus='.$warehouseStatus;
//Price by customer
if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) {
$urloption .= '&socid='.$socid;
@@ -2357,7 +2358,7 @@ class Form
$out .= img_picto($langs->trans("Search"), 'search');
}
} else {
- $out .= $this->select_produits_list($selected, $htmlname, $filtertype, $limit, $price_level, '', $status, $finished, 0, $socid, $showempty, $forcecombo, $morecss, $hidepriceinlabel, $warehouseStatus);
+ $out .= $this->select_produits_list($selected, $htmlname, $filtertype, $limit, $price_level, '', $status, $finished, 0, $socid, $showempty, $forcecombo, $morecss, $hidepriceinlabel, $warehouseStatus, $status_purchase);
}
if (empty($nooutput)) {
@@ -2453,9 +2454,10 @@ class Form
* 'warehouseopen' = count products from open warehouses,
* 'warehouseclosed' = count products from closed warehouses,
* 'warehouseinternal' = count products from warehouses for internal correct/transfer only
+ * @param int $status_purchase Purchase status -1=Return all products, 0=Products not on purchase, 1=Products on purchase
* @return array Array of keys for json
*/
- public function select_produits_list($selected = '', $htmlname = 'productid', $filtertype = '', $limit = 20, $price_level = 0, $filterkey = '', $status = 1, $finished = 2, $outputmode = 0, $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $hidepriceinlabel = 0, $warehouseStatus = '')
+ public function select_produits_list($selected = '', $htmlname = 'productid', $filtertype = '', $limit = 20, $price_level = 0, $filterkey = '', $status = 1, $finished = 2, $outputmode = 0, $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $hidepriceinlabel = 0, $warehouseStatus = '', $status_purchase = -1)
{
// phpcs:enable
global $langs, $conf;
@@ -2593,6 +2595,9 @@ class Form
} elseif ($status >= 0) {
$sql .= " AND p.tosell = ".((int) $status);
}
+ if ($status_purchase >= 0) {
+ $sql .= " AND p.tobuy = ".((int) $status_purchase);
+ }
// Filter by product type
if (strval($filtertype) != '') {
$sql .= " AND p.fk_product_type = ".((int) $filtertype);
@@ -7379,7 +7384,18 @@ class Form
$objecttmp = null;
- $InfoFieldList = explode(":", $objectdesc);
+ // Example of value for $objectdec:
+ // Bom:bom/class/bom.class.php:0:t.status=1
+ // Bom:bom/class/bom.class.php:0:t.status=1:ref
+ // Bom:bom/class/bom.class.php:0:(t.status:=:1):ref
+ $InfoFieldList = explode(":", $objectdesc, 4);
+ $vartmp = $InfoFieldList[3];
+ $reg = array();
+ if (preg_match('/^.*:(\w*)$/', $vartmp, $reg)) {
+ $InfoFieldList[4] = $reg[1]; // take the sort field
+ }
+ $InfoFieldList[3] = preg_replace('/:\w*$/', '', $vartmp); // take the filter field
+
$classname = $InfoFieldList[0];
$classpath = $InfoFieldList[1];
$addcreatebuttonornot = empty($InfoFieldList[2]) ? 0 : $InfoFieldList[2];
@@ -8122,8 +8138,15 @@ class Form
}
$out .= '};'."\n";
$out .= '$(document).ready(function () {
- $(\'#'.$htmlname.'\').'.$tmpplugin.'({
- dir: \'ltr\',
+ $(\'#'.$htmlname.'\').'.$tmpplugin.'({';
+ if ($placeholder) {
+ $out .= '
+ placeholder: {
+ id: \'-1\',
+ text: \''.dol_escape_js($placeholder).'\'
+ },';
+ }
+ $out .= ' dir: \'ltr\',
// Specify format function for dropdown item
formatResult: formatResult,
templateResult: formatResult, /* For 4.0 */
@@ -9740,24 +9763,45 @@ class Form
$ret = '';
- $ret .= '';
+ $ret .= '
';
return $ret;
}
diff --git a/htdocs/core/class/html.formother.class.php b/htdocs/core/class/html.formother.class.php
index c47646419aa..ad0c74ab9a8 100644
--- a/htdocs/core/class/html.formother.class.php
+++ b/htdocs/core/class/html.formother.class.php
@@ -460,7 +460,7 @@ class FormOther
* @param string $htmlname Name of combo list (example: 'search_sale')
* @param User $user Object user
* @param int $showstatus 0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status
- * @param int|string $showempty 1=show also an empty value
+ * @param int|string $showempty 1=show also an empty value or text to show for empty
* @param string $morecss More CSS
* @param int $norepresentative Show also an entry "Not categorized"
* @return string Html combo list code
@@ -489,12 +489,12 @@ class FormOther
$out .= '
';
if ($showempty) {
$textforempty = ' ';
- if (!empty($conf->use_javascript_ajax)) {
- $textforempty = ' '; // If we use ajaxcombo, we need here to avoid to have an empty element that is too small.
- }
if (!is_numeric($showempty)) {
$textforempty = $showempty;
}
+ if (!empty($conf->use_javascript_ajax) && $textforempty == ' ') {
+ $textforempty = ' '; // If we use ajaxcombo, we need here to avoid to have an empty element that is too small.
+ }
$out .= ''.$textforempty.' '."\n";
}
@@ -1479,9 +1479,10 @@ class FormOther
* @param array $search_groupby Array of preselected fields
* @param array $arrayofgroupby Array of groupby to fill
* @param string $morecss More CSS
+ * @param string $showempty '1' or 'text'
* @return string HTML string component
*/
- public function selectGroupByField($object, $search_groupby, &$arrayofgroupby, $morecss = 'minwidth200 maxwidth250')
+ public function selectGroupByField($object, $search_groupby, &$arrayofgroupby, $morecss = 'minwidth200 maxwidth250', $showempty = '1')
{
global $langs, $extrafields, $form;
@@ -1493,7 +1494,7 @@ class FormOther
$SS = substr($langs->trans("Second"), 0, 1).substr($langs->trans("Second"), 0, 1);
foreach ($object->fields as $key => $val) {
- if (!$val['measure']) {
+ if (!$val['isameasure']) {
if (in_array($key, array(
'id', 'ref_int', 'ref_ext', 'rowid', 'entity', 'last_main_doc', 'logo', 'logo_squarred', 'extraparams',
'parent', 'photo', 'socialnetworks', 'webservices_url', 'webservices_key'))) {
@@ -1541,7 +1542,7 @@ class FormOther
foreach ($arrayofgroupby as $key => $val) {
$arrayofgroupbylabel[$key] = $val['label'];
}
- $result = $form->selectarray('search_groupby', $arrayofgroupbylabel, $search_groupby, 1, 0, 0, '', 0, 0, 0, '', $morecss, 1);
+ $result = $form->selectarray('search_groupby', $arrayofgroupbylabel, $search_groupby, $showempty, 0, 0, '', 0, 0, 0, '', $morecss, 1);
return $result;
}
@@ -1552,9 +1553,10 @@ class FormOther
* @param mixed $object Object analyzed
* @param array $search_xaxis Array of preselected fields
* @param array $arrayofxaxis Array of groupby to fill
- * @return string HTML string component
+ * @param string $showempty '1' or 'text'
+ * @return string HTML string component
*/
- public function selectXAxisField($object, $search_xaxis, &$arrayofxaxis)
+ public function selectXAxisField($object, $search_xaxis, &$arrayofxaxis, $showempty = '1')
{
global $langs, $extrafields, $form;
@@ -1589,9 +1591,9 @@ class FormOther
continue;
}
if (in_array($val['type'], array('timestamp', 'date', 'datetime'))) {
- $arrayofxaxis['t.'.$key.'-year'] = array('label' => $langs->trans($val['label']).' ('.$YYYY.')', 'position' => $val['position'].'-y');
- $arrayofxaxis['t.'.$key.'-month'] = array('label' => $langs->trans($val['label']).' ('.$YYYY.'-'.$MM.')', 'position' => $val['position'].'-m');
- $arrayofxaxis['t.'.$key.'-day'] = array('label' => $langs->trans($val['label']).' ('.$YYYY.'-'.$MM.'-'.$DD.')', 'position' => $val['position'].'-d');
+ $arrayofxaxis['t.'.$key.'-year'] = array('label' => $langs->trans($val['label']).' ('.$YYYY.') ', 'position' => $val['position'].'-y');
+ $arrayofxaxis['t.'.$key.'-month'] = array('label' => $langs->trans($val['label']).' ('.$YYYY.'-'.$MM.') ', 'position' => $val['position'].'-m');
+ $arrayofxaxis['t.'.$key.'-day'] = array('label' => $langs->trans($val['label']).' ('.$YYYY.'-'.$MM.'-'.$DD.') ', 'position' => $val['position'].'-d');
} else {
$arrayofxaxis['t.'.$key] = array('label' => $langs->trans($val['label']), 'position' => (int) $val['position']);
}
@@ -1617,7 +1619,7 @@ class FormOther
foreach ($arrayofxaxis as $key => $val) {
$arrayofxaxislabel[$key] = $val['label'];
}
- $result = $form->selectarray('search_xaxis', $arrayofxaxislabel, $search_xaxis, 1, 0, 0, '', 0, 0, 0, '', 'minwidth250', 1);
+ $result = $form->selectarray('search_xaxis', $arrayofxaxislabel, $search_xaxis, $showempty, 0, 0, '', 0, 0, 0, '', 'minwidth250', 1);
return $result;
}
diff --git a/htdocs/core/customreports.php b/htdocs/core/customreports.php
index fafd1c015e8..f1616feb21b 100644
--- a/htdocs/core/customreports.php
+++ b/htdocs/core/customreports.php
@@ -99,7 +99,8 @@ $arrayoftype = array(
'order' => array('label' => 'Orders', 'ObjectClassName' => 'Commande', 'enabled' => $conf->commande->enabled, 'ClassPath' => "/commande/class/commande.class.php"),
'invoice' => array('label' => 'Invoices', 'ObjectClassName' => 'Facture', 'enabled' => $conf->facture->enabled, 'ClassPath' => "/compta/facture/class/facture.class.php"),
'invoice_template'=>array('label' => 'PredefinedInvoices', 'ObjectClassName' => 'FactureRec', 'enabled' => $conf->facture->enabled, 'ClassPath' => "/compta/class/facturerec.class.php", 'langs'=>'bills'),
- 'contract' => array('label' => 'Contracts', 'ObjectClassName' => 'Contrat', 'enabled' => $conf->contrat->enabled, 'ClassPath' => "/contrat/class/contrat.class.php", 'langs'=>'contract'),
+ 'contract' => array('label' => 'Contracts', 'ObjectClassName' => 'Contrat', 'enabled' => $conf->contrat->enabled, 'ClassPath' => "/contrat/class/contrat.class.php", 'langs'=>'contracts'),
+ 'contractdet' => array('label' => 'ContractLines', 'ObjectClassName' => 'ContratLigne', 'enabled' => $conf->contrat->enabled, 'ClassPath' => "/contrat/class/contrat.class.php", 'langs'=>'contracts'),
'bom' => array('label' => 'BOM', 'ObjectClassName' => 'Bom', 'enabled' => $conf->bom->enabled),
'mo' => array('label' => 'MO', 'ObjectClassName' => 'Mo', 'enabled' => $conf->mrp->enabled, 'ClassPath' => "/mrp/class/mo.class.php"),
'ticket' => array('label' => 'Ticket', 'ObjectClassName' => 'Ticket', 'enabled' => $conf->ticket->enabled),
@@ -159,6 +160,11 @@ $search_array_options = $extrafields->getOptionalsFromPost($object->table_elemen
$search_component_params = array('');
$search_component_params_hidden = GETPOST('search_component_params_hidden', 'alphanohtml');
+// For the case we enter a criteria manually, the search_component_params_input will be defined and must be used in priority
+if (GETPOST('search_component_params_input', 'alphanohtml')) {
+ $search_component_params_hidden = GETPOST('search_component_params_input', 'alphanohtml');
+}
+
$MAXUNIQUEVALFORGROUP = 20;
$MAXMEASURESINBARGRAPH = 20;
@@ -175,7 +181,12 @@ $arrayofgroupby = array();
$arrayofyaxis = array();
$arrayofvaluesforgroupby = array();
-restrictedArea($user, $object->element, 0, '');
+$features = $object->element;
+if (!empty($object->element_for_permission)) {
+ $features = $object->element_for_permission;
+}
+
+restrictedArea($user, $features, 0, '');
$error = 0;
@@ -420,22 +431,22 @@ if ($object->isextrafieldmanaged) {
}
}
}
-print ' '.$langs->trans("Measures").'
';
-print $form->multiselectarray('search_measures', $arrayofmesures, $search_measures, 0, 0, 'minwidth400', 1);
+print '
';
+print $form->multiselectarray('search_measures', $arrayofmesures, $search_measures, 0, 0, 'minwidth400', 1, 0, '', '', $langs->trans("Measures")); // Fill the array $arrayofmeasures with possible fields
print ' ';
// XAxis
print '';
-print '
'.$langs->trans("XAxis").'
';
-print $formother->selectXAxisField($object, $search_xaxis, $arrayofxaxis);
+print '
';
+print $formother->selectXAxisField($object, $search_xaxis, $arrayofxaxis, $langs->trans("XAxis")); // Fill the array $arrayofxaxis with possible fields
print '
';
// Group by
print '';
-print '
'.$langs->trans("GroupBy").'
';
-print $formother->selectGroupByField($object, $search_groupby, $arrayofgroupby);
+print '
';
+print $formother->selectGroupByField($object, $search_groupby, $arrayofgroupby, 'minwidth200 maxwidth250', $langs->trans("GroupBy")); // Fill the array $arrayofgroupby with possible fields
print '
';
@@ -561,7 +572,7 @@ if (!empty($search_measures) && !empty($search_xaxis)) {
$sql .= ' AND entity IN ('.getEntity($object->element).')';
}
// Add the where here
- $sqlfilters = GETPOST('search_component_params_hidden', 'alphanohtml');
+ $sqlfilters = $search_component_params_hidden;
if ($sqlfilters) {
$errormessage = '';
if (dolCheckFilters($sqlfilters, $errormessage)) {
diff --git a/htdocs/core/db/DoliDB.class.php b/htdocs/core/db/DoliDB.class.php
index 4476228d509..f23a66bbee4 100644
--- a/htdocs/core/db/DoliDB.class.php
+++ b/htdocs/core/db/DoliDB.class.php
@@ -302,8 +302,8 @@ abstract class DoliDB implements Database
/**
* Convert (by PHP) a PHP server TZ string date into a Timestamps date (GMT if gm=true)
- * 19700101020000 -> 3600 with TZ+1 and gmt=0
- * 19700101020000 -> 7200 whaterver is TZ if gmt=1
+ * 19700101020000 -> 3600 with server TZ = +1 and $gm='tzserver'
+ * 19700101020000 -> 7200 whaterver is server TZ if $gm='gmt'
*
* @param string $string Date in a string (YYYYMMDDHHMMSS, YYYYMMDD, YYYY-MM-DD HH:MM:SS)
* @param mixed $gm 'gmt'=Input informations are GMT values, 'tzserver'=Local to server TZ
diff --git a/htdocs/core/js/dst.js b/htdocs/core/js/dst.js
index 83d4abd5f08..8433ada72a9 100644
--- a/htdocs/core/js/dst.js
+++ b/htdocs/core/js/dst.js
@@ -26,7 +26,8 @@
$(document).ready(function () {
var timezone = jstz.determine();
-
+ console.log("Timezone detected for user: "+timezone.name());
+
// Detect and save TZ and DST
var rightNow = new Date();
var jan1 = new Date(rightNow.getFullYear(), 0, 1, 0, 0, 0, 0);
diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php
index 2d46ee2a239..4bf8a0e7219 100644
--- a/htdocs/core/lib/company.lib.php
+++ b/htdocs/core/lib/company.lib.php
@@ -199,7 +199,7 @@ function societe_prepare_head(Societe $object)
if (empty($conf->global->SOCIETE_DISABLE_BANKACCOUNT)) {
$nbBankAccount = 0;
$foundonexternalonlinesystem = 0;
- $langs->load("banks");
+ $langs->load("bills");
$title = $langs->trans("PaymentModes");
diff --git a/htdocs/core/lib/date.lib.php b/htdocs/core/lib/date.lib.php
index d4028e2196b..237adc9447a 100644
--- a/htdocs/core/lib/date.lib.php
+++ b/htdocs/core/lib/date.lib.php
@@ -357,18 +357,18 @@ function dolSqlDateFilter($datefield, $day_date, $month_date, $year_date, $exclu
* Convert a string date into a GM Timestamps date
* Warning: YYYY-MM-DDTHH:MM:SS+02:00 (RFC3339) is not supported. If parameter gm is 1, we will use no TZ, if not we will use TZ of server, not the one inside string.
*
- * @param string $string Date in a string
- * YYYYMMDD
- * YYYYMMDDHHMMSS
- * YYYYMMDDTHHMMSSZ
- * YYYY-MM-DDTHH:MM:SSZ (RFC3339)
- * DD/MM/YY or DD/MM/YYYY (deprecated)
- * DD/MM/YY HH:MM:SS or DD/MM/YYYY HH:MM:SS (deprecated)
- * @param int $gm 1 =Input date is GM date,
- * 0 =Input date is local date using PHP server timezone
- * @return int Date as a timestamp
- * 19700101020000 -> 7200 with gm=1
- * 19700101000000 -> 0 with gm=1
+ * @param string $string Date in a string
+ * YYYYMMDD
+ * YYYYMMDDHHMMSS
+ * YYYYMMDDTHHMMSSZ
+ * YYYY-MM-DDTHH:MM:SSZ (RFC3339)
+ * DD/MM/YY or DD/MM/YYYY (deprecated)
+ * DD/MM/YY HH:MM:SS or DD/MM/YYYY HH:MM:SS (deprecated)
+ * @param int|string $gm 'gmt' or 1 =Input date is GM date,
+ * 'tzserver' or 0 =Input date is date using PHP server timezone
+ * @return int Date as a timestamp
+ * 19700101020000 -> 7200 with gm=1
+ * 19700101000000 -> 0 with gm=1
*
* @see dol_print_date(), dol_mktime(), dol_getdate()
*/
@@ -408,7 +408,14 @@ function dol_stringtotime($string, $gm = 1)
$string = preg_replace('/([^0-9])/i', '', $string);
$tmp = $string.'000000';
- $date = dol_mktime(substr($tmp, 8, 2), substr($tmp, 10, 2), substr($tmp, 12, 2), substr($tmp, 4, 2), substr($tmp, 6, 2), substr($tmp, 0, 4), ($gm ? 1 : 0));
+ // Clean $gm
+ if ($gm === 1) {
+ $gm = 'gmt';
+ } elseif (empty($gm) || $gm === 'tzserver') {
+ $gm = 'tzserver';
+ }
+
+ $date = dol_mktime(substr($tmp, 8, 2), substr($tmp, 10, 2), substr($tmp, 12, 2), substr($tmp, 4, 2), substr($tmp, 6, 2), substr($tmp, 0, 4), $gm);
return $date;
}
diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php
index 4439a38509b..9361bf5a206 100644
--- a/htdocs/core/lib/functions.lib.php
+++ b/htdocs/core/lib/functions.lib.php
@@ -353,12 +353,14 @@ function GETPOSTISSET($paramname)
}
}
}
- // If there is saved contextpage, page or limit
+ // If there is saved contextpage, limit, page or mode
if ($paramname == 'contextpage' && !empty($_SESSION['lastsearch_contextpage_'.$relativepathstring])) {
$isset = true;
+ } elseif ($paramname == 'limit' && !empty($_SESSION['lastsearch_limit_'.$relativepathstring])) {
+ $isset = true;
} elseif ($paramname == 'page' && !empty($_SESSION['lastsearch_page_'.$relativepathstring])) {
$isset = true;
- } elseif ($paramname == 'limit' && !empty($_SESSION['lastsearch_limit_'.$relativepathstring])) {
+ } elseif ($paramname == 'mode' && !empty($_SESSION['lastsearch_mode_'.$relativepathstring])) {
$isset = true;
}
} else {
@@ -448,10 +450,12 @@ function GETPOST($paramname, $check = 'alphanohtml', $method = 0, $filter = null
// If there is saved contextpage, page or limit
if ($paramname == 'contextpage' && !empty($_SESSION['lastsearch_contextpage_'.$relativepathstring])) {
$out = $_SESSION['lastsearch_contextpage_'.$relativepathstring];
- } elseif ($paramname == 'page' && !empty($_SESSION['lastsearch_page_'.$relativepathstring])) {
- $out = $_SESSION['lastsearch_page_'.$relativepathstring];
} elseif ($paramname == 'limit' && !empty($_SESSION['lastsearch_limit_'.$relativepathstring])) {
$out = $_SESSION['lastsearch_limit_'.$relativepathstring];
+ } elseif ($paramname == 'page' && !empty($_SESSION['lastsearch_page_'.$relativepathstring])) {
+ $out = $_SESSION['lastsearch_page_'.$relativepathstring];
+ } elseif ($paramname == 'mode' && !empty($_SESSION['lastsearch_mode_'.$relativepathstring])) {
+ $out = $_SESSION['lastsearch_mode_'.$relativepathstring];
}
} elseif (!isset($_GET['sortfield'])) {
// Else, retrieve default values if we are not doing a sort
@@ -2569,11 +2573,11 @@ function dol_mktime($hour, $minute, $second, $month, $day, $year, $gm = 'auto',
{
global $conf;
//print "- ".$hour.",".$minute.",".$second.",".$month.",".$day.",".$year.",".$_SERVER["WINDIR"]." -";
- //print 'gm:'.$gm.' gm==auto:'.($gm == 'auto').' ';
if ($gm === 'auto') {
$gm = (empty($conf) ? 'tzserver' : $conf->tzuserinputkey);
}
+ //print 'gm:'.$gm.' gm === auto:'.($gm === 'auto').' ';exit;
// Clean parameters
if ($hour == -1 || empty($hour)) {
@@ -3719,7 +3723,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $
if (empty($srconly) && in_array($pictowithouttext, array(
'1downarrow', '1uparrow', '1leftarrow', '1rightarrow', '1uparrow_selected', '1downarrow_selected', '1leftarrow_selected', '1rightarrow_selected',
'accountancy', 'accounting_account', 'account', 'accountline', 'action', 'add', 'address', 'angle-double-down', 'angle-double-up', 'asset',
- 'bank_account', 'barcode', 'bank', 'bell', 'bill', 'billa', 'billr', 'billd', 'bookmark', 'bom', 'bug', 'building',
+ 'bank_account', 'barcode', 'bank', 'bell', 'bill', 'billa', 'billr', 'billd', 'bookmark', 'bom', 'briefcase-medical', 'bug', 'building',
'card', 'calendar', 'calendarmonth', 'calendarweek', 'calendarday', 'calendarperuser', 'calendarpertype',
'cash-register', 'category', 'chart', 'check', 'clock', 'close_title', 'cog', 'collab', 'company', 'contact', 'country', 'contract', 'conversation', 'cron', 'cubes',
'multicurrency',
@@ -3745,7 +3749,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $
'recent', 'reception', 'recruitmentcandidature', 'recruitmentjobposition', 'resource', 'recurring',
'shapes', 'square', 'stop-circle', 'supplier', 'supplier_proposal', 'supplier_order', 'supplier_invoice',
'timespent', 'title_setup', 'title_accountancy', 'title_bank', 'title_hrm', 'title_agenda',
- 'uncheck', 'user-cog', 'vat', 'website', 'workstation',
+ 'uncheck', 'user-cog', 'user-injured', 'user-md', 'vat', 'website', 'workstation',
'conferenceorbooth', 'eventorganization'
))) {
$fakey = $pictowithouttext;
@@ -10797,7 +10801,7 @@ function dolForgeCriteriaCallback($matches)
{
global $db;
- //dol_syslog("Convert matches ".$matches[1]);
+ dol_syslog("Convert matches ".$matches[1]);
if (empty($matches[1])) {
return '';
}
diff --git a/htdocs/core/lib/geturl.lib.php b/htdocs/core/lib/geturl.lib.php
index 3eb8448fcde..8d992250cbb 100644
--- a/htdocs/core/lib/geturl.lib.php
+++ b/htdocs/core/lib/geturl.lib.php
@@ -87,7 +87,7 @@ function getURLContent($url, $postorget = 'GET', $param = '', $followlocation =
// Turning off the server and peer verification(TrustManager Concept).
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, ($ssl_verifypeer ? true : false));
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, ($ssl_verifypeer ? true : false));
// Restrict use to some protocols only
$protocols = 0;
diff --git a/htdocs/core/lib/invoice.lib.php b/htdocs/core/lib/invoice.lib.php
index 1e4cdf16791..c6f972f46c8 100644
--- a/htdocs/core/lib/invoice.lib.php
+++ b/htdocs/core/lib/invoice.lib.php
@@ -200,7 +200,7 @@ function invoice_rec_prepare_head($object)
$h = 0;
$head = array();
- $head[$h][0] = DOL_URL_ROOT.'/compta/facture/card-rec.php?id='.$object->id;
+ $head[$h][0] = DOL_URL_ROOT . '/compta/facture/card-rec.php?id=' . $object->id;
$head[$h][1] = $langs->trans("RepeatableInvoice");
$head[$h][2] = 'card';
$h++;
@@ -216,6 +216,35 @@ function invoice_rec_prepare_head($object)
return $head;
}
+/**
+ * Return array head with list of tabs to view object informations.
+ *
+ * @param Facture $object Invoice object
+ * @return array head array with tabs
+ */
+function supplier_invoice_rec_prepare_head($object)
+{
+ global $db, $langs, $conf;
+
+ $h = 0;
+ $head = array();
+
+ $head[$h][0] = DOL_URL_ROOT . '/fourn/facture/card-rec.php?id=' . $object->id;
+ $head[$h][1] = $langs->trans("RepeatableSupplierInvoice");
+ $head[$h][2] = 'card';
+ $h++;
+
+ // Show more tabs from modules
+ // Entries must be declared in modules descriptor with line
+ // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
+ // $this->tabs = array('entity:-tabname); to remove a tab
+ complete_head_from_modules($conf, $langs, $object, $head, $h, 'invoice_supplier_rec');
+
+ complete_head_from_modules($conf, $langs, $object, $head, $h, 'invoice_supplier_rec', 'remove');
+
+ return $head;
+}
+
/**
* Return a HTML table that contains a pie chart of customer invoices
*
diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php
index dcf9fafd103..a0c6bcfd054 100644
--- a/htdocs/core/lib/pdf.lib.php
+++ b/htdocs/core/lib/pdf.lib.php
@@ -1065,12 +1065,12 @@ function pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_
$line3 .= ($line3 ? " - " : "").$outputlangs->convToOutputCharset(getFormeJuridiqueLabel($fromcompany->forme_juridique_code));
}
// Capital
- if (!empty($fromcompany->capital) && $fromcompany->capital) {
- $tmpamounttoshow = price2num($fromcompany->capital); // This field is a free string
+ if (!empty($fromcompany->capital)) {
+ $tmpamounttoshow = price2num($fromcompany->capital); // This field is a free string or a float
if (is_numeric($tmpamounttoshow) && $tmpamounttoshow > 0) {
$line3 .= ($line3 ? " - " : "").$outputlangs->transnoentities("CapitalOf", price($tmpamounttoshow, 0, $outputlangs, 0, 0, 0, $conf->currency));
- } else {
- $line3 .= ($line3 ? " - " : "").$outputlangs->transnoentities("CapitalOf", $tmpamounttoshow, $outputlangs);
+ } elseif (!empty($fromcompany->capital)) {
+ $line3 .= ($line3 ? " - " : "").$outputlangs->transnoentities("CapitalOf", $fromcompany->capital, $outputlangs);
}
}
// Prof Id 1
diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php
index 4a20fbf96f2..ccdfa261fc8 100644
--- a/htdocs/core/lib/security.lib.php
+++ b/htdocs/core/lib/security.lib.php
@@ -892,8 +892,10 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl
}
if ($feature == 'expensereport') {
$useridtocheck = $object->fk_user_author;
- if (!in_array($useridtocheck, $childids)) {
- return false;
+ if (!$user->rights->expensereport->readall) {
+ if (!in_array($useridtocheck, $childids)) {
+ return false;
+ }
}
}
}
diff --git a/htdocs/core/lib/xcal.lib.php b/htdocs/core/lib/xcal.lib.php
index fcd1660985b..97ada3e3d4f 100644
--- a/htdocs/core/lib/xcal.lib.php
+++ b/htdocs/core/lib/xcal.lib.php
@@ -100,6 +100,7 @@ function build_calfile($format, $title, $desc, $events_array, $outputfile)
$created = $event["created"];
$modified = $event["modified"];
$assignedUsers = $event["assignedUsers"];
+ //print $fulldayevent.' '.dol_print_date($startdate, 'dayhour', 'gmt');
// Format
$summary = format_cal($format, $summary);
@@ -191,16 +192,16 @@ function build_calfile($format, $title, $desc, $events_array, $outputfile)
// Date must be GMT dates
// Current date
- fwrite($calfileh, "DTSTAMP:".dol_print_date($now, "dayhourxcard", true)."\n");
+ fwrite($calfileh, "DTSTAMP:".dol_print_date($now, "dayhourxcard", 'gmt')."\n");
// Start date
$prefix = "";
- $startdatef = dol_print_date($startdate, "dayhourxcard", true);
+ $startdatef = dol_print_date($startdate, "dayhourxcard", 'gmt');
if ($fulldayevent) {
// Local time
$prefix = ";VALUE=DATE";
- $startdatef = dol_print_date($startdate, "dayxcard", false);
+ $startdatef = dol_print_date($startdate, "dayxcard", 'gmt');
}
fwrite($calfileh, "DTSTART".$prefix.":".$startdatef."\n");
@@ -208,6 +209,9 @@ function build_calfile($format, $title, $desc, $events_array, $outputfile)
// End date
if ($fulldayevent) {
if (empty($enddate)) {
+ // We add 1 day needed for full day event (DTEND must be next day after event).
+ // This is mention in https://datatracker.ietf.org/doc/html/rfc5545:
+ // "The "DTEND" property for a "VEVENT" calendar component specifies the non-inclusive end of the event."
$enddate = dol_time_plus_duree($startdate, 1, "d");
}
} else {
@@ -217,14 +221,14 @@ function build_calfile($format, $title, $desc, $events_array, $outputfile)
}
$prefix = "";
- $enddatef = dol_print_date($enddate, "dayhourxcard", true);
+ $enddatef = dol_print_date($enddate, "dayhourxcard", 'gmt');
if ($fulldayevent) {
$prefix = ";VALUE=DATE";
- $enddatef = dol_print_date($enddate + 1, "dayxcard", false);
-
- // Local time
- //$enddatef .= dol_print_date($enddate+1,"dayhourxcard",false);
+ // We add 1 second so we reach the +1 day needed for full day event (DTEND must be next day after event)
+ // This is mention in https://datatracker.ietf.org/doc/html/rfc5545:
+ // "The "DTEND" property for a "VEVENT" calendar component specifies the non-inclusive end of the event."
+ $enddatef = dol_print_date($enddate + 1, "dayxcard", 'gmt');
}
fwrite($calfileh, "DTEND".$prefix.":".$enddatef."\n");
@@ -256,11 +260,11 @@ function build_calfile($format, $title, $desc, $events_array, $outputfile)
}
if ($created) {
- fwrite($calfileh, "CREATED:".dol_print_date($created, "dayhourxcard", true)."\n");
+ fwrite($calfileh, "CREATED:".dol_print_date($created, "dayhourxcard", 'gmt')."\n");
}
if ($modified) {
- fwrite($calfileh, "LAST-MODIFIED:".dol_print_date($modified, "dayhourxcard", true)."\n");
+ fwrite($calfileh, "LAST-MODIFIED:".dol_print_date($modified, "dayhourxcard", 'gmt')."\n");
}
fwrite($calfileh, "SUMMARY:".$encoding.$summary."\n");
@@ -270,7 +274,7 @@ function build_calfile($format, $title, $desc, $events_array, $outputfile)
fwrite($calfileh, "LOCATION:".$location."\n");
fwrite($calfileh, "TRANSP:OPAQUE\n");
fwrite($calfileh, "CLASS:CONFIDENTIAL\n");
- fwrite($calfileh, "DTSTAMP:".dol_print_date($startdatef, "dayhourxcard", true)."\n");
+ fwrite($calfileh, "DTSTAMP:".dol_print_date($startdatef, "dayhourxcard", 'gmt')."\n");
fwrite($calfileh, "END:VJOURNAL\n");
}
diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php
index 58ddeb0fbf3..e69644bd123 100644
--- a/htdocs/core/menus/standard/eldy.lib.php
+++ b/htdocs/core/menus/standard/eldy.lib.php
@@ -1087,6 +1087,8 @@ function print_left_eldy_menu($db, $menu_array_before, $menu_array_after, &$tabM
$newmenu->add("/fourn/facture/list.php?leftmenu=suppliers_bills_paid&search_status=2", $langs->trans("BillShortStatusPaid"), 2, $user->rights->fournisseur->facture->lire, '', $mainmenu, 'suppliers_bills_paid');
}
+ $newmenu->add("/fourn/facture/list-rec.php?leftmenu=supplierinvoicestemplate_list", $langs->trans("ListOfTemplates"), 1, $user->rights->fournisseur->facture->lire, '', $mainmenu, 'supplierinvoicestemplate_list');
+
$newmenu->add("/fourn/paiement/list.php?leftmenu=suppliers_bills_payment", $langs->trans("Payments"), 1, $user->rights->fournisseur->facture->lire, '', $mainmenu, 'suppliers_bills_payment');
if ($usemenuhider || empty($leftmenu) || preg_match('/suppliers_bills/', $leftmenu)) {
diff --git a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php
index 210ef249ac2..d30107fcbfb 100644
--- a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php
+++ b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php
@@ -1216,35 +1216,6 @@ class pdf_eratosthene extends ModelePDFCommandes
}
//}
- // VAT
- foreach ($this->tva_array as $tvakey => $tvaval) {
- if ($tvakey != 0) { // On affiche pas taux 0
- $this->atleastoneratenotnull++;
-
- $index++;
- $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
-
- $tvacompl = '';
- if (preg_match('/\*/', $tvakey)) {
- $tvakey = str_replace('*', '', $tvakey);
- $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
- }
- $totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalVAT", $mysoc->country_code) : '');
- $totalvat .= ' ';
- if (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'rateonly') {
- $totalvat .= vatrate($tvaval['vatrate'], 1).$tvacompl;
- } elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'codeonly') {
- $totalvat .= $tvaval['vatcode'].$tvacompl;
- } else {
- $totalvat .= vatrate($tvaval['vatrate'], 1).($tvaval['vatcode'] ? ' ('.$tvaval['vatcode'].')' : '').$tvacompl;
- }
- $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
-
- $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
- $pdf->MultiCell($largcol2, $tab2_hl, price(price2num($tvaval['amount'], 'MT'), 0, $outputlangs), 0, 'R', 1);
- }
- }
-
// VAT
foreach ($this->tva_array as $tvakey => $tvaval) {
if ($tvakey != 0) { // On affiche pas taux 0
diff --git a/htdocs/core/modules/modAsset.class.php b/htdocs/core/modules/modAsset.class.php
index 3a51a366970..b275f38debe 100644
--- a/htdocs/core/modules/modAsset.class.php
+++ b/htdocs/core/modules/modAsset.class.php
@@ -215,6 +215,11 @@ class modAsset extends DolibarrModules
*/
public function init($options = '')
{
+ $result = $this->_load_tables('/install/mysql/tables/', 'asset');
+ if ($result < 0) {
+ return -1; // Do not activate module if error 'not allowed' returned when loading module SQL queries (the _load_table run sql with run_sql with the error allowed parameter set to 'default')
+ }
+
// Permissions
$this->remove($options);
diff --git a/htdocs/core/modules/modFournisseur.class.php b/htdocs/core/modules/modFournisseur.class.php
index 0f730f773bb..8bd801e0daa 100644
--- a/htdocs/core/modules/modFournisseur.class.php
+++ b/htdocs/core/modules/modFournisseur.class.php
@@ -129,6 +129,25 @@ class modFournisseur extends DolibarrModules
6=>array('file'=>'box_supplier_orders_awaiting_reception.php', 'enabledbydefaulton'=>'Home'),
);
+ $arraydate = dol_getdate(dol_now());
+ $datestart = dol_mktime(23, 0, 0, $arraydate['mon'], $arraydate['mday'], $arraydate['year']);
+ $this->cronjobs = array(
+ 0 => array(
+ 'label'=>'RecurringSupplierInvoices',
+ 'jobtype'=>'method',
+ 'class'=>'fourn/class/fournisseur.facture-rec.class.php',
+ 'objectname'=>'FactureFournisseurRec',
+ 'method'=>'createRecurringInvoices',
+ 'parameters'=>'',
+ 'comment'=>'Generate recurring supplier invoices',
+ 'frequency'=>1,
+ 'unitfrequency'=>3600 * 24,
+ 'priority'=>50,
+ 'status'=>1,
+ 'datestart'=>$datestart
+ ));
+
+
// Permissions
$this->rights = array();
$this->rights_class = 'fournisseur';
diff --git a/htdocs/core/modules/modMailing.class.php b/htdocs/core/modules/modMailing.class.php
index dfd292aa847..1a31aad9c8b 100644
--- a/htdocs/core/modules/modMailing.class.php
+++ b/htdocs/core/modules/modMailing.class.php
@@ -159,6 +159,11 @@ class modMailing extends DolibarrModules
*/
public function init($options = '')
{
+ $result = $this->_load_tables('/install/mysql/tables/', 'mailing');
+ if ($result < 0) {
+ return -1; // Do not activate module if error 'not allowed' returned when loading module SQL queries (the _load_table run sql with run_sql with the error allowed parameter set to 'default')
+ }
+
// Permissions
$this->remove($options);
diff --git a/htdocs/core/modules/modTicket.class.php b/htdocs/core/modules/modTicket.class.php
index 01561b40b01..68cb3f45551 100644
--- a/htdocs/core/modules/modTicket.class.php
+++ b/htdocs/core/modules/modTicket.class.php
@@ -106,7 +106,8 @@ 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/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)
);
@@ -320,6 +321,11 @@ class modTicket extends DolibarrModules
{
global $conf, $langs;
+ $result = $this->_load_tables('/install/mysql/tables/', 'ticket');
+ if ($result < 0) {
+ return -1; // Do not activate module if error 'not allowed' returned when loading module SQL queries (the _load_table run sql with run_sql with the error allowed parameter set to 'default')
+ }
+
// Permissions
$this->remove($options);
diff --git a/htdocs/core/tpl/extrafields_list_search_title.tpl.php b/htdocs/core/tpl/extrafields_list_search_title.tpl.php
index 0a61e51d33d..2283d111cbc 100644
--- a/htdocs/core/tpl/extrafields_list_search_title.tpl.php
+++ b/htdocs/core/tpl/extrafields_list_search_title.tpl.php
@@ -37,6 +37,9 @@ if (!empty($extrafieldsobjectkey)) { // $extrafieldsobject is the $object->table
$tooltip = empty($extrafields->attributes[$extrafieldsobjectkey]['help'][$key]) ? '' : $extrafields->attributes[$extrafieldsobjectkey]['help'][$key];
print getTitleFieldOfList($extrafields->attributes[$extrafieldsobjectkey]['label'][$key], 0, $_SERVER["PHP_SELF"], $sortonfield, "", $param, ($align ? 'align="'.$align.'" data-titlekey="'.$key.'"' : 'data-titlekey="'.$key.'"'), $sortfield, $sortorder, '', $disablesortlink, $tooltip)."\n";
+ if (isset($totalarray) && isset($totalarray['nbfield'])) {
+ $totalarray['nbfield']++;
+ }
}
}
}
diff --git a/htdocs/core/tpl/login.tpl.php b/htdocs/core/tpl/login.tpl.php
index c07e01570c2..ccec4352e89 100644
--- a/htdocs/core/tpl/login.tpl.php
+++ b/htdocs/core/tpl/login.tpl.php
@@ -31,7 +31,7 @@ if (empty($conf) || !is_object($conf)) {
}
// DDOS protection
-$size = (int) $_SERVER['CONTENT_LENGTH'];
+$size = (empty($_SERVER['CONTENT_LENGTH']) ? 0 : (int) $_SERVER['CONTENT_LENGTH']);
if ($size > 10000) {
http_response_code(413);
$langs->loadLangs(array("errors", "install"));
@@ -136,7 +136,7 @@ $(document).ready(function () {
-
+
diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php
index 8d21a789648..335754a8168 100644
--- a/htdocs/core/tpl/objectline_create.tpl.php
+++ b/htdocs/core/tpl/objectline_create.tpl.php
@@ -65,7 +65,7 @@ $colspan = 3; // Columns: total ht + col edit + col delete
if (!empty($conf->multicurrency->enabled) && $this->multicurrency_code != $conf->currency) {
$colspan++; //Add column for Total (currency) if required
}
-if (in_array($object->element, array('propal', 'commande', 'order', 'facture', 'facturerec', 'invoice', 'supplier_proposal', 'order_supplier', 'invoice_supplier'))) {
+if (in_array($object->element, array('propal', 'commande', 'order', 'facture', 'facturerec', 'invoice', 'supplier_proposal', 'order_supplier', 'invoice_supplier', 'invoice_supplier_rec'))) {
$colspan++; // With this, there is a column move button
}
@@ -89,6 +89,8 @@ if (!empty($extrafields)) {
$objectline = new SupplierInvoiceLine($this->db);
} elseif ($this->table_element_line == 'facturedet_rec') {
$objectline = new FactureLigneRec($this->db);
+ } elseif ($this->table_element_line == 'facture_fourn_det_rec') {
+ $objectline = new FactureFournisseurLigneRec($this->db);
}
}
print "\n";
@@ -103,7 +105,7 @@ if ($nolinesbefore) {
trans('AddNewLine'); ?>
element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier') { // We must have same test in printObjectLines
+ if ($object->element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier' || $object->element == 'invoice_supplier_rec') { // We must have same test in printObjectLines
?>
trans('SupplierRef'); ?>
global->MAIN_DOLEDITOR_HEIGHT) ? 100 : $conf->global->MAIN_DOLEDITOR_HEIGHT), $toolbarname, '', false, true, $enabled, $nbrows, '98%');
$doleditor->Create();
// Show autofill date for recurring invoices
- if (!empty($conf->service->enabled) && $object->element == 'facturerec') {
+ if (!empty($conf->service->enabled) && ($object->element == 'facturerec' || $object->element == 'invoice_supplier_rec')) {
echo '';
echo $langs->trans('AutoFillDateFrom').' ';
echo $form->selectyesno('date_start_fill', $line->date_start_fill, 1);
@@ -362,7 +364,7 @@ if ($nolinesbefore) {
}
}
echo '';
- if ($object->element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier') { // We must have same test in printObjectLines
+ if ($object->element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier' || $object->element == 'invoice_supplier_rec') { // We must have same test in printObjectLines
$coldisplay++;
?>
">
diff --git a/htdocs/core/tpl/objectline_edit.tpl.php b/htdocs/core/tpl/objectline_edit.tpl.php
index ea7b039b550..0f0043eadd6 100644
--- a/htdocs/core/tpl/objectline_edit.tpl.php
+++ b/htdocs/core/tpl/objectline_edit.tpl.php
@@ -66,7 +66,7 @@ $colspan = 3; // Col total ht + col edit + col delete
if (!empty($inputalsopricewithtax)) {
$colspan++; // We add 1 if col total ttc
}
-if (in_array($object->element, array('propal', 'supplier_proposal', 'facture', 'facturerec', 'invoice', 'commande', 'order', 'order_supplier', 'invoice_supplier'))) {
+if (in_array($object->element, array('propal', 'supplier_proposal', 'facture', 'facturerec', 'invoice', 'commande', 'order', 'order_supplier', 'invoice_supplier', 'invoice_supplier_rec'))) {
$colspan++; // With this, there is a column move button
}
if (!empty($conf->multicurrency->enabled) && $this->multicurrency_code != $conf->currency) {
@@ -170,7 +170,11 @@ $coldisplay++;
}
// Show autofill date for recuring invoices
- if (!empty($conf->service->enabled) && $line->product_type == 1 && $line->element == 'facturedetrec') {
+ if (!empty($conf->service->enabled) && $line->product_type == 1 && ($line->element == 'facturedetrec' || $line->element == 'invoice_supplier_det_rec')) {
+ if ($line->element == 'invoice_supplier_det_rec') {
+ $line->date_start_fill = $line->date_start;
+ $line->date_end_fill = $line->date_end;
+ }
echo '
';
echo $langs->trans('AutoFillDateFrom').' ';
echo $form->selectyesno('date_start_fill', GETPOSTISSET('date_start_fill') ? GETPOST('date_start_fill', 'int') : $line->date_start_fill, 1);
@@ -183,7 +187,7 @@ $coldisplay++;
element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier') { // We must have same test in printObjectLines
+ if ($object->element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier' || $object->element == 'invoice_supplier_rec') { // We must have same test in printObjectLines
$coldisplay++;
?>
diff --git a/htdocs/core/tpl/objectline_title.tpl.php b/htdocs/core/tpl/objectline_title.tpl.php
index e1f89b18937..0f86289dfe1 100644
--- a/htdocs/core/tpl/objectline_title.tpl.php
+++ b/htdocs/core/tpl/objectline_title.tpl.php
@@ -55,7 +55,7 @@ if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) {
print '
'.$langs->trans('Description').' ';
// Supplier ref
-if ($this->element == 'supplier_proposal' || $this->element == 'order_supplier' || $this->element == 'invoice_supplier') {
+if ($this->element == 'supplier_proposal' || $this->element == 'order_supplier' || $this->element == 'invoice_supplier' || $this->element == 'invoice_supplier_rec') {
print '
'.$langs->trans("SupplierRef").' ';
}
diff --git a/htdocs/core/tpl/objectline_view.tpl.php b/htdocs/core/tpl/objectline_view.tpl.php
index c4ddc7d0c4c..36eceb87341 100644
--- a/htdocs/core/tpl/objectline_view.tpl.php
+++ b/htdocs/core/tpl/objectline_view.tpl.php
@@ -162,7 +162,11 @@ if (($line->info_bits & 2) == 2) {
}
// Show date range
- if ($line->element == 'facturedetrec') {
+ if ($line->element == 'facturedetrec' || $line->element == 'invoice_supplier_det_rec') {
+ if ($line->element == 'invoice_supplier_det_rec' && $line->product_type != Product::TYPE_PRODUCT) {
+ $line->date_start_fill = $line->date_start;
+ $line->date_end_fill = $line->date_end;
+ }
if ($line->date_start_fill || $line->date_end_fill) {
print '
';
}
@@ -202,6 +206,8 @@ if (($line->info_bits & 2) == 2) {
if ($line->fk_product > 0 && !empty($conf->global->PRODUIT_DESC_IN_FORM)) {
if ($line->element == 'facturedetrec') {
print (!empty($line->description) && $line->description != $line->product_label) ? (($line->date_start_fill || $line->date_end_fill) ? '' : '
').'
'.dol_htmlentitiesbr($line->description) : '';
+ } elseif ($line->element == 'invoice_supplier_det_rec') {
+ print (!empty($line->description) && $line->description != $line->label) ? (($line->date_start || $line->date_end) ? '' : '
').'
'.dol_htmlentitiesbr($line->description) : '';
} else {
print (!empty($line->description) && $line->description != $line->product_label) ? (($line->date_start || $line->date_end) ? '' : '
').'
'.dol_htmlentitiesbr($line->description) : '';
}
@@ -239,7 +245,7 @@ if (!empty($conf->accounting->enabled) && $line->fk_accounting_account > 0) {
}
print '';
-if ($object->element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier') { // We must have same test in printObjectLines
+if ($object->element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier' || $object->element == 'invoice_supplier_rec') { // We must have same test in printObjectLines
print '
';
print ($line->ref_fourn ? $line->ref_fourn : $line->ref_supplier);
print ' ';
diff --git a/htdocs/delivery/class/delivery.class.php b/htdocs/delivery/class/delivery.class.php
index 6bfe3a33dd7..3241461ace1 100644
--- a/htdocs/delivery/class/delivery.class.php
+++ b/htdocs/delivery/class/delivery.class.php
@@ -725,7 +725,7 @@ class Delivery extends CommonObject
*/
public function getNomUrl($withpicto = 0, $save_lastsearch_value = -1)
{
- global $langs;
+ global $langs, $hookmanager;
$result = '';
@@ -757,6 +757,16 @@ class Delivery extends CommonObject
$result .= ' ';
}
$result .= $linkstart.$this->ref.$linkend;
+
+ global $action;
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) {
+ $result = $hookmanager->resPrint;
+ } else {
+ $result .= $hookmanager->resPrint;
+ }
return $result;
}
diff --git a/htdocs/don/class/don.class.php b/htdocs/don/class/don.class.php
index cbd5a386354..0ce92f44e1b 100644
--- a/htdocs/don/class/don.class.php
+++ b/htdocs/don/class/don.class.php
@@ -913,7 +913,7 @@ class Don extends CommonObject
*/
public function getNomUrl($withpicto = 0, $notooltip = 0, $moretitle = '', $save_lastsearch_value = -1)
{
- global $conf, $langs;
+ global $conf, $langs, $hookmanager;
if (!empty($conf->dol_no_mouse_hover)) {
$notooltip = 1; // Force disable tooltips
@@ -953,7 +953,15 @@ class Don extends CommonObject
$result .= $this->ref;
}
$result .= $linkend;
-
+ global $action;
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) {
+ $result = $hookmanager->resPrint;
+ } else {
+ $result .= $hookmanager->resPrint;
+ }
return $result;
}
diff --git a/htdocs/don/class/paymentdonation.class.php b/htdocs/don/class/paymentdonation.class.php
index b5775ce18ac..0f8db03597d 100644
--- a/htdocs/don/class/paymentdonation.class.php
+++ b/htdocs/don/class/paymentdonation.class.php
@@ -661,7 +661,7 @@ class PaymentDonation extends CommonObject
*/
public function getNomUrl($withpicto = 0, $maxlen = 0)
{
- global $langs;
+ global $langs, $hookmanager;
$result = '';
@@ -684,6 +684,15 @@ class PaymentDonation extends CommonObject
}
}
+ global $action;
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) {
+ $result = $hookmanager->resPrint;
+ } else {
+ $result .= $hookmanager->resPrint;
+ }
return $result;
}
}
diff --git a/htdocs/ecm/class/ecmdirectory.class.php b/htdocs/ecm/class/ecmdirectory.class.php
index 03413a56eb1..f99a567a314 100644
--- a/htdocs/ecm/class/ecmdirectory.class.php
+++ b/htdocs/ecm/class/ecmdirectory.class.php
@@ -474,7 +474,7 @@ class EcmDirectory extends CommonObject
*/
public function getNomUrl($withpicto = 0, $option = '', $max = 0, $more = '', $notooltip = 0)
{
- global $langs;
+ global $langs, $hookmanager;
$result = '';
//$newref=str_replace('_',' ',$this->ref);
@@ -506,6 +506,15 @@ class EcmDirectory extends CommonObject
}
$result .= $linkend;
+ global $action;
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) {
+ $result = $hookmanager->resPrint;
+ } else {
+ $result .= $hookmanager->resPrint;
+ }
return $result;
}
diff --git a/htdocs/ecm/class/ecmfiles.class.php b/htdocs/ecm/class/ecmfiles.class.php
index 6c2b8fc4023..2f9bf4c41e5 100644
--- a/htdocs/ecm/class/ecmfiles.class.php
+++ b/htdocs/ecm/class/ecmfiles.class.php
@@ -831,7 +831,7 @@ class EcmFiles extends CommonObject
{
global $db, $conf, $langs;
global $dolibarr_main_authentication, $dolibarr_main_demo;
- global $menumanager;
+ global $menumanager, $hookmanager;
if (!empty($conf->dol_no_mouse_hover)) {
$notooltip = 1; // Force disable tooltips
@@ -868,6 +868,16 @@ class EcmFiles extends CommonObject
}
}
$result .= $linkstart.$this->ref.$linkend;
+
+ global $action;
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) {
+ $result = $hookmanager->resPrint;
+ } else {
+ $result .= $hookmanager->resPrint;
+ }
return $result;
}
diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php
index 17fe55d0583..032ee4b534b 100644
--- a/htdocs/emailcollector/class/emailcollector.class.php
+++ b/htdocs/emailcollector/class/emailcollector.class.php
@@ -563,7 +563,7 @@ class EmailCollector extends CommonObject
global $action, $hookmanager;
$hookmanager->initHooks(array('emailcollectordao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
diff --git a/htdocs/emailcollector/class/emailcollectoraction.class.php b/htdocs/emailcollector/class/emailcollectoraction.class.php
index bd044f37d0f..eaa4b0737b9 100644
--- a/htdocs/emailcollector/class/emailcollectoraction.class.php
+++ b/htdocs/emailcollector/class/emailcollectoraction.class.php
@@ -389,7 +389,7 @@ class EmailCollectorAction extends CommonObject
global $action, $hookmanager;
$hookmanager->initHooks(array('emailcollectoractiondao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
diff --git a/htdocs/emailcollector/class/emailcollectorfilter.class.php b/htdocs/emailcollector/class/emailcollectorfilter.class.php
index d926a8bf14f..a99c5198d72 100644
--- a/htdocs/emailcollector/class/emailcollectorfilter.class.php
+++ b/htdocs/emailcollector/class/emailcollectorfilter.class.php
@@ -363,7 +363,7 @@ class EmailCollectorFilter extends CommonObject
global $action, $hookmanager;
$hookmanager->initHooks(array('emailcollectorfilterdao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
diff --git a/htdocs/eventorganization/class/conferenceorbooth.class.php b/htdocs/eventorganization/class/conferenceorbooth.class.php
index 1d462ddae30..15493425231 100644
--- a/htdocs/eventorganization/class/conferenceorbooth.class.php
+++ b/htdocs/eventorganization/class/conferenceorbooth.class.php
@@ -602,7 +602,7 @@ class ConferenceOrBooth extends ActionComm
global $action, $hookmanager;
$hookmanager->initHooks(array('conferenceorboothdao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
diff --git a/htdocs/eventorganization/class/conferenceorboothattendee.class.php b/htdocs/eventorganization/class/conferenceorboothattendee.class.php
index 96131aa5946..bdd81660a12 100644
--- a/htdocs/eventorganization/class/conferenceorboothattendee.class.php
+++ b/htdocs/eventorganization/class/conferenceorboothattendee.class.php
@@ -855,7 +855,7 @@ class ConferenceOrBoothAttendee extends CommonObject
global $action, $hookmanager;
$hookmanager->initHooks(array('conferenceorboothattendeedao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
diff --git a/htdocs/expedition/class/expedition.class.php b/htdocs/expedition/class/expedition.class.php
index 837c82be361..8490fa67753 100644
--- a/htdocs/expedition/class/expedition.class.php
+++ b/htdocs/expedition/class/expedition.class.php
@@ -11,7 +11,7 @@
* Copyright (C) 2015 Claudio Aschieri
* Copyright (C) 2016-2021 Ferran Marcet
* Copyright (C) 2018 Nicolas ZABOURI
- * Copyright (C) 2018-2020 Frédéric France
+ * Copyright (C) 2018-2022 Frédéric France
* Copyright (C) 2020 Lenin Rivas
*
* This program is free software; you can redistribute it and/or modify
@@ -1778,7 +1778,7 @@ class Expedition extends CommonObject
*/
public function getNomUrl($withpicto = 0, $option = '', $max = 0, $short = 0, $notooltip = 0, $save_lastsearch_value = -1)
{
- global $langs, $conf;
+ global $langs, $conf, $hookmanager;
$result = '';
$label = ''.$langs->trans("Shipment").' ';
@@ -1824,7 +1824,15 @@ class Expedition extends CommonObject
$result .= $this->ref;
}
$result .= $linkend;
-
+ global $action;
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) {
+ $result = $hookmanager->resPrint;
+ } else {
+ $result .= $hookmanager->resPrint;
+ }
return $result;
}
diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php
index 70dad3ff48f..be49b0a8c0c 100644
--- a/htdocs/expensereport/class/expensereport.class.php
+++ b/htdocs/expensereport/class/expensereport.class.php
@@ -1640,7 +1640,7 @@ class ExpenseReport extends CommonObject
*/
public function getNomUrl($withpicto = 0, $option = '', $max = 0, $short = 0, $moretitle = '', $notooltip = 0, $save_lastsearch_value = -1)
{
- global $langs, $conf;
+ global $langs, $conf, $hookmanager;
$result = '';
@@ -1709,6 +1709,15 @@ class ExpenseReport extends CommonObject
}
$result .= $linkend;
+ global $action;
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) {
+ $result = $hookmanager->resPrint;
+ } else {
+ $result .= $hookmanager->resPrint;
+ }
return $result;
}
diff --git a/htdocs/expensereport/class/paymentexpensereport.class.php b/htdocs/expensereport/class/paymentexpensereport.class.php
index 3aac0cee2b8..5f9e9f17e6f 100644
--- a/htdocs/expensereport/class/paymentexpensereport.class.php
+++ b/htdocs/expensereport/class/paymentexpensereport.class.php
@@ -628,7 +628,7 @@ class PaymentExpenseReport extends CommonObject
*/
public function getNomUrl($withpicto = 0, $maxlen = 0)
{
- global $langs;
+ global $langs, $hookmanager;
$result = '';
@@ -660,7 +660,15 @@ class PaymentExpenseReport extends CommonObject
$result .= $link.($maxlen ?dol_trunc($this->ref, $maxlen) : $this->ref).$linkend;
}
}
-
+ global $action;
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) {
+ $result = $hookmanager->resPrint;
+ } else {
+ $result .= $hookmanager->resPrint;
+ }
return $result;
}
diff --git a/htdocs/fichinter/class/fichinter.class.php b/htdocs/fichinter/class/fichinter.class.php
index 7a532998b1f..b6505aa1ecf 100644
--- a/htdocs/fichinter/class/fichinter.class.php
+++ b/htdocs/fichinter/class/fichinter.class.php
@@ -816,7 +816,7 @@ class Fichinter extends CommonObject
global $action;
$hookmanager->initHooks(array('interventiondao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
diff --git a/htdocs/fichinter/class/fichinterrec.class.php b/htdocs/fichinter/class/fichinterrec.class.php
index ee385cbc7a4..fa97cf3e8a5 100644
--- a/htdocs/fichinter/class/fichinterrec.class.php
+++ b/htdocs/fichinter/class/fichinterrec.class.php
@@ -628,7 +628,7 @@ class FichinterRec extends Fichinter
*/
public function getNomUrl($withpicto = 0, $option = '', $max = 0, $short = 0, $moretitle = '')
{
- global $langs;
+ global $langs, $hookmanager;
$result = '';
$label = $langs->trans("ShowInterventionModel").': '.$this->ref;
@@ -653,6 +653,15 @@ class FichinterRec extends Fichinter
if ($withpicto != 2) {
$result .= $link.$this->ref.$linkend;
}
+ global $action;
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) {
+ $result = $hookmanager->resPrint;
+ } else {
+ $result .= $hookmanager->resPrint;
+ }
return $result;
}
diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php
index aefb8741668..8a0e0de299e 100644
--- a/htdocs/fourn/class/fournisseur.commande.class.php
+++ b/htdocs/fourn/class/fournisseur.commande.class.php
@@ -9,7 +9,7 @@
* Copyright (C) 2013 Florian Henry
* Copyright (C) 2013 Cédric Salvador
* Copyright (C) 2018 Nicolas ZABOURI
- * Copyright (C) 2018-2020 Frédéric France
+ * Copyright (C) 2018-2022 Frédéric France
* Copyright (C) 2018-2021 Ferran Marcet
* Copyright (C) 2021 Josep Lluís Amador
*
@@ -472,17 +472,21 @@ class CommandeFournisseur extends CommonOrder
$sql .= " l.date_start, l.date_end,";
$sql .= ' l.fk_multicurrency, l.multicurrency_code, l.multicurrency_subprice, l.multicurrency_total_ht, l.multicurrency_total_tva, l.multicurrency_total_ttc';
if (!empty($conf->global->PRODUCT_USE_SUPPLIER_PACKAGING)) {
- $sql .= ", pfp.rowid as fk_pfp, pfp.packaging";
+ $sql .= ", pfp.rowid as fk_pfp, pfp.packaging, MAX(pfp.quantity) as max_qty";
}
$sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as l";
$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON l.fk_product = p.rowid';
if (!empty($conf->global->PRODUCT_USE_SUPPLIER_PACKAGING)) {
- $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price as pfp ON l.fk_product = pfp.fk_product and l.ref = pfp.ref_fourn AND pfp.fk_soc = ".((int) $this->socid);
+ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price as pfp ON pfp.entity IN (".getEntity('product_fournisseur_price').") AND l.fk_product = pfp.fk_product and l.ref = pfp.ref_fourn AND pfp.fk_soc = ".((int) $this->socid);
}
$sql .= " WHERE l.fk_commande = ".((int) $this->id);
if ($only_product) {
$sql .= ' AND p.fk_product_type = 0';
}
+ if (!empty($conf->global->PRODUCT_USE_SUPPLIER_PACKAGING)) {
+ $sql.= " AND l.qty >= pfp.quantity ";
+ $sql.= " GROUP BY l.rowid HAVING max_qty = MAX(pfp.quantity) ";
+ }
$sql .= " ORDER BY l.rang, l.rowid";
//print $sql;
@@ -787,7 +791,7 @@ class CommandeFournisseur extends CommonOrder
*/
public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $save_lastsearch_value = -1, $addlinktonotes = 0)
{
- global $langs, $conf, $user;
+ global $langs, $conf, $user, $hookmanager;
$result = '';
@@ -869,6 +873,15 @@ class CommandeFournisseur extends CommonOrder
}
}
+ global $action;
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) {
+ $result = $hookmanager->resPrint;
+ } else {
+ $result .= $hookmanager->resPrint;
+ }
return $result;
}
@@ -3014,16 +3027,12 @@ class CommandeFournisseur extends CommonOrder
// phpcs:enable
global $conf, $langs;
- $clause = " WHERE";
-
$sql = "SELECT c.rowid, c.date_creation as datec, c.date_commande, c.fk_statut, c.date_livraison as delivery_date, c.total_ht";
$sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseur as c";
if (empty($user->rights->societe->client->voir) && !$user->socid) {
- $sql .= " JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON c.fk_soc = sc.fk_soc";
- $sql .= " WHERE sc.fk_user = ".((int) $user->id);
- $clause = " AND";
+ $sql .= " JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
}
- $sql .= $clause." c.entity = ".$conf->entity;
+ $sql .= " WHERE c.entity = ".$conf->entity;
if ($mode === 'awaiting') {
$sql .= " AND c.fk_statut IN (".self::STATUS_ORDERSENT.", ".self::STATUS_RECEIVED_PARTIALLY.")";
} else {
@@ -3123,18 +3132,19 @@ class CommandeFournisseur extends CommonOrder
$outputlangs->load("products");
if (!dol_strlen($modele)) {
- $modele = 'muscadet';
-
+ $modele = '';
if ($this->model_pdf) {
$modele = $this->model_pdf;
} elseif (!empty($conf->global->COMMANDE_SUPPLIER_ADDON_PDF)) {
$modele = $conf->global->COMMANDE_SUPPLIER_ADDON_PDF;
}
}
-
- $modelpath = "core/modules/supplier_order/doc/";
-
- return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
+ if (empty($modele)) {
+ return 0;
+ } else {
+ $modelpath = "core/modules/supplier_order/doc/";
+ return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
+ }
}
/**
@@ -3537,14 +3547,17 @@ class CommandeFournisseurLigne extends CommonOrderLine
$sql .= ' cd.date_start, cd.date_end, cd.fk_unit,';
$sql .= ' cd.multicurrency_subprice, cd.multicurrency_total_ht, cd.multicurrency_total_tva, cd.multicurrency_total_ttc';
if (!empty($conf->global->PRODUCT_USE_SUPPLIER_PACKAGING)) {
- $sql .= ", pfp.rowid as fk_pfp, pfp.packaging";
+ $sql .= ", pfp.rowid as fk_pfp, pfp.packaging, MAX(pfp.quantity) as max_qty";
}
$sql .= ' FROM '.MAIN_DB_PREFIX.'commande_fournisseurdet as cd';
$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON cd.fk_product = p.rowid';
if (!empty($conf->global->PRODUCT_USE_SUPPLIER_PACKAGING)) {
- $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price as pfp ON cd.fk_product = pfp.fk_product and cd.ref = pfp.ref_fourn";
+ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price as pfp ON pfp.entity IN (".getEntity('product_fournisseur_price').") AND cd.fk_product = pfp.fk_product and cd.ref = pfp.ref_fourn";
}
$sql .= ' WHERE cd.rowid = '.((int) $rowid);
+ if (!empty($conf->global->PRODUCT_USE_SUPPLIER_PACKAGING)) {
+ $sql .= " AND cd.qty >= pfp.quantity GROUP BY cd.rowid HAVING max_qty = MAX(pfp.quantity)";
+ }
$result = $this->db->query($sql);
if ($result) {
$objp = $this->db->fetch_object($result);
diff --git a/htdocs/fourn/class/fournisseur.facture-rec.class.php b/htdocs/fourn/class/fournisseur.facture-rec.class.php
new file mode 100644
index 00000000000..c8f0ad75536
--- /dev/null
+++ b/htdocs/fourn/class/fournisseur.facture-rec.class.php
@@ -0,0 +1,2200 @@
+
+ * Copyright (C) 2004-2019 Laurent Destailleur
+ * Copyright (C) 2009-2012 Regis Houssin
+ * Copyright (C) 2010-2011 Juanjo Menent
+ * Copyright (C) 2012 Cedric Salvador
+ * Copyright (C) 2013 Florian Henry
+ * Copyright (C) 2015 Marcos García
+ * Copyright (C) 2017-2020 Frédéric France
+ *
+ * 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 .
+ */
+
+/**
+ * \file htdocs/fourn/facture/class/fournisseur.facture-rec.class.php
+ * \ingroup facture
+ * \brief Fichier de la classe des factures fournisseursrecurentes
+ */
+
+require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
+require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
+require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
+
+
+/**
+ * Class to manage invoice templates
+ */
+class FactureFournisseurRec extends CommonInvoice
+{
+ /**
+ * @var string ID to identify managed object
+ */
+ public $element = 'invoice_supplier_rec';
+
+ /**
+ * @var string Name of table without prefix where object is stored
+ */
+ public $table_element = 'facture_fourn_rec';
+
+ /**
+ * @var string Name of subtable line
+ */
+ public $table_element_line = 'facture_fourn_det_rec';
+
+ /**
+ * @var string Field with ID of parent key if this field has a parent
+ */
+ public $fk_element = 'fk_facture_fourn';
+
+ /**
+ * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
+ */
+ public $picto = 'bill';
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $table_ref_field = 'titre';
+
+ /**
+ * @var string The label of recurring invoice
+ */
+ public $titre;
+ public $ref_supplier;
+ public $socid;
+
+ public $suspended;
+ public $libelle;
+ public $amount;
+ public $remise;
+ public $vat_src_code;
+ public $localtax1;
+ public $localtax2;
+
+ public $user_author;
+ public $user_modif;
+ public $fk_project;
+
+ public $mode_reglement_id;
+ public $mode_reglement_code;
+ public $cond_reglement_code;
+ public $cond_reglement_doc;
+ public $cond_reglement_id;
+
+ public $date_lim_reglement;
+
+ public $fk_multicurrency;
+ public $multicurrency_code;
+ public $multicurrency_tx;
+ public $multicurrency_total_ht;
+ public $multicurrency_total_tva;
+ public $multicurrency_total_ttc;
+
+ public $usenewprice = 0;
+ public $frequency;
+ public $unit_frequency;
+ public $date_when;
+ public $date_last_gen;
+ public $nb_gen_done;
+ public $nb_gen_max;
+ public $auto_validate; // 0 to create in draft, 1 to create and validate the new invoice
+ public $generate_pdf; // 1 to generate PDF on invoice generation (default)
+
+ public $model_pdf;
+
+ /* Override fields in CommonObject
+ public $entity;
+ public $date_creation;
+ public $date_modification;
+ public $total_ht;
+ public $total_tva;
+ public $total_ttc;
+ public $fk_account;
+ public $mode_reglement;
+ public $cond_reglement;
+ public $note_public;
+ public $note_private;
+ */
+
+ /**
+ * 'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password')
+ * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)"
+ * 'label' the translation key.
+ * 'enabled' is a condition when the field must be managed.
+ * 'position' is the sort order of field.
+ * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0).
+ * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing)
+ * 'noteditable' says if field is not editable (1 or 0)
+ * 'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created.
+ * 'index' if we want an index in database.
+ * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...).
+ * 'searchall' is 1 if we want to search in this field when making a search from the quick search button.
+ * 'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8).
+ * 'css' is the CSS style to use on field. For example: 'maxwidth200'
+ * 'help' is a string visible as a tooltip on field
+ * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record
+ * 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code.
+ * 'arrayofkeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel")
+ * 'comment' is not used. You can store here any text of your choice. It is not used by application.
+ *
+ * Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor.
+ */
+
+ // BEGIN MODULEBUILDER PROPERTIES
+ /**
+ * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor.
+ */
+ public $fields = array(
+ 'rowid' =>array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>10),
+ 'titre' =>array('type'=>'varchar(100)', 'label'=>'Titre', 'enabled'=>1, 'showoncombobox' => 1, 'visible'=>-1, 'position'=>15),
+ 'ref_supplier' =>array('type'=>'varchar(180)', 'label'=>'RefSupplier', 'enabled'=>1, 'showoncombobox' => 1, 'visible'=>-1, 'position'=>20),
+ 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'default'=>1, 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>25, 'index'=>1),
+ 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>30),
+ 'datec' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'position'=>35),
+ 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>40),
+ 'suspended' =>array('type'=>'integer', 'label'=>'Suspended', 'enabled'=>1, 'visible'=>-1, 'position'=>225),
+ 'libelle' =>array('type'=>'varchar(100)', 'label'=>'Libelle', 'enabled'=>1, 'showoncombobox' => 0, 'visible'=>-1, 'position'=>15),
+ 'amount' =>array('type'=>'double(24,8)', 'label'=>'Amount', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>35),
+ 'remise' =>array('type'=>'double', 'label'=>'Remise', 'enabled'=>1, 'visible'=>-1, 'position'=>40),
+
+ 'localtax1' =>array('type'=>'double(24,8)', 'label'=>'Localtax1', 'enabled'=>1, 'visible'=>-1, 'position'=>60, 'isameasure'=>1),
+ 'localtax2' =>array('type'=>'double(24,8)', 'label'=>'Localtax2', 'enabled'=>1, 'visible'=>-1, 'position'=>65, 'isameasure'=>1),
+ 'total_ht' =>array('type'=>'double(24,8)', 'label'=>'Total', 'enabled'=>1, 'visible'=>-1, 'position'=>70, 'isameasure'=>1),
+ 'total_tva' =>array('type'=>'double(24,8)', 'label'=>'Tva', 'enabled'=>1, 'visible'=>-1, 'position'=>55, 'isameasure'=>1),
+ 'total_ttc' =>array('type'=>'double(24,8)', 'label'=>'Total ttc', 'enabled'=>1, 'visible'=>-1, 'position'=>75, 'isameasure'=>1),
+
+ 'fk_user_author' =>array('type'=>'integer:User:user/class/user.class.php', 'label'=>'Fk user author', 'enabled'=>1, 'visible'=>-1, 'position'=>80),
+ 'fk_user_modif' =>array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>1, 'visible'=>-2, 'notnull'=>-1, 'position'=>210),
+ 'fk_projet' =>array('type'=>'integer:Project:projet/class/project.class.php:1:fk_statut=1', 'label'=>'Fk projet', 'enabled'=>1, 'visible'=>-1, 'position'=>85),
+ 'fk_account' =>array('type'=>'integer', 'label'=>'Fk account', 'enabled'=>1, 'visible'=>-1, 'position'=>175),
+ 'fk_cond_reglement' =>array('type'=>'integer', 'label'=>'Fk cond reglement', 'enabled'=>1, 'visible'=>-1, 'position'=>90),
+ 'fk_mode_reglement' =>array('type'=>'integer', 'label'=>'Fk mode reglement', 'enabled'=>1, 'visible'=>-1, 'position'=>95),
+ 'date_lim_reglement' =>array('type'=>'date', 'label'=>'Date lim reglement', 'enabled'=>1, 'visible'=>-1, 'position'=>100),
+
+ 'note_private' =>array('type'=>'text', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>105),
+ 'note_public' =>array('type'=>'text', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>110),
+ 'modelpdf' =>array('type'=>'varchar(255)', 'label'=>'Modelpdf', 'enabled'=>1, 'visible'=>-1, 'position'=>115),
+
+ 'fk_multicurrency' =>array('type'=>'integer', 'label'=>'Fk multicurrency', 'enabled'=>1, 'visible'=>-1, 'position'=>180),
+ 'multicurrency_code' =>array('type'=>'varchar(255)', 'label'=>'Multicurrency code', 'enabled'=>1, 'visible'=>-1, 'position'=>185),
+ 'multicurrency_tx' =>array('type'=>'double(24,8)', 'label'=>'Multicurrency tx', 'enabled'=>1, 'visible'=>-1, 'position'=>190, 'isameasure'=>1),
+ 'multicurrency_total_ht' =>array('type'=>'double(24,8)', 'label'=>'Multicurrency total ht', 'enabled'=>1, 'visible'=>-1, 'position'=>195, 'isameasure'=>1),
+ 'multicurrency_total_tva' =>array('type'=>'double(24,8)', 'label'=>'Multicurrency total tva', 'enabled'=>1, 'visible'=>-1, 'position'=>200, 'isameasure'=>1),
+ 'multicurrency_total_ttc' =>array('type'=>'double(24,8)', 'label'=>'Multicurrency total ttc', 'enabled'=>1, 'visible'=>-1, 'position'=>205, 'isameasure'=>1),
+
+ 'usenewprice' =>array('type'=>'integer', 'label'=>'UseNewPrice', 'enabled'=>1, 'visible'=>0, 'position'=>155),
+ 'frequency' =>array('type'=>'integer', 'label'=>'Frequency', 'enabled'=>1, 'visible'=>-1, 'position'=>150),
+ 'unit_frequency' =>array('type'=>'varchar(2)', 'label'=>'Unit frequency', 'enabled'=>1, 'visible'=>-1, 'position'=>125),
+
+ 'date_when' =>array('type'=>'datetime', 'label'=>'Date when', 'enabled'=>1, 'visible'=>-1, 'position'=>130),
+ 'date_last_gen' =>array('type'=>'datetime', 'label'=>'Date last gen', 'enabled'=>1, 'visible'=>-1, 'position'=>135),
+ 'nb_gen_done' =>array('type'=>'integer', 'label'=>'Nb gen done', 'enabled'=>1, 'visible'=>-1, 'position'=>140),
+ 'nb_gen_max' =>array('type'=>'integer', 'label'=>'Nb gen max', 'enabled'=>1, 'visible'=>-1, 'position'=>145),
+ 'revenuestamp' =>array('type'=>'double(24,8)', 'label'=>'RevenueStamp', 'enabled'=>1, 'visible'=>-1, 'position'=>160, 'isameasure'=>1),
+ 'auto_validate' =>array('type'=>'integer', 'label'=>'Auto validate', 'enabled'=>1, 'visible'=>-1, 'position'=>165),
+ 'generate_pdf' =>array('type'=>'integer', 'label'=>'Generate pdf', 'enabled'=>1, 'visible'=>-1, 'position'=>170),
+
+ );
+ // END MODULEBUILDER PROPERTIES
+
+ const STATUS_NOTSUSPENDED = 0;
+ const STATUS_SUSPENDED = 1;
+
+
+
+ /**
+ * Constructor
+ *
+ * @param DoliDB $db Database handler
+ */
+ public function __construct($db)
+ {
+ $this->db = $db;
+ }
+
+ /**
+ * Create a predefined supplier invoice
+ *
+ * @param User $user User object
+ * @param int $facFournId Id invoice
+ * @param int $notrigger No trigger
+ * @return int <0 if KO, id of invoice created if OK
+ */
+ public function create($user, $facFournId, $notrigger = 0)
+ {
+ global $conf;
+
+ $error = 0;
+ $now = dol_now();
+
+ // Clean parameters
+ $this->titre = empty($this->titre) ? '' : $this->titre;
+ $this->ref_supplier = empty($this->ref_supplier) ? '' : $this->ref_supplier;
+ $this->usenewprice = empty($this->usenewprice) ? 0 : $this->usenewprice;
+ $this->suspended = empty($this->suspended) ? 0 : $this->suspended;
+ // No frequency defined then no next date to execution
+ if (empty($this->frequency)) {
+ $this->frequency = 0;
+ $this->date_when = null;
+ }
+ $this->frequency = abs($this->frequency);
+ $this->nb_gen_done = 0;
+ $this->nb_gen_max = empty($this->nb_gen_max) ? 0 : $this->nb_gen_max;
+ $this->auto_validate = empty($this->auto_validate) ? 0 : $this->auto_validate;
+ $this->generate_pdf = empty($this->generate_pdf) ? 0 : $this->generate_pdf;
+
+ $this->db->begin();
+
+ // On charge la facture fournisseur depuis laquelle on crée la facture fournisseur modèle
+ $facfourn_src = new FactureFournisseur($this->db);
+ $result = $facfourn_src->fetch($facFournId);
+ if ($result > 0) {
+ $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'facture_fourn_rec (';
+ $sql .= 'titre';
+ $sql .= ', ref_supplier';
+ $sql .= ', entity';
+ $sql .= ', fk_soc';
+ $sql .= ', datec';
+ $sql .= ', suspended';
+ $sql .= ', libelle';
+ $sql .= ', amount';
+ $sql .= ', remise';
+ $sql .= ', fk_user_author';
+ $sql .= ', fk_projet';
+ $sql .= ', fk_account';
+ $sql .= ', fk_cond_reglement';
+ $sql .= ', fk_mode_reglement';
+ $sql .= ', date_lim_reglement';
+ $sql .= ', note_private';
+ $sql .= ', note_public';
+ $sql .= ', modelpdf';
+ $sql .= ', fk_multicurrency';
+ $sql .= ', multicurrency_code';
+ $sql .= ', multicurrency_tx';
+ $sql .= ', usenewprice';
+ $sql .= ', frequency';
+ $sql .= ', unit_frequency';
+ $sql .= ', date_when';
+ $sql .= ', date_last_gen';
+ $sql .= ', nb_gen_done';
+ $sql .= ', nb_gen_max';
+ $sql .= ', auto_validate';
+ $sql .= ', generate_pdf';
+ $sql .= ') VALUES (';
+ $sql .= "'".$this->db->escape($this->titre)."'";
+ $sql .= ", '".$this->db->escape($this->ref_supplier)."'";
+ $sql .= ', ' . (int) $conf->entity;
+ $sql .= ', ' . (int) $facfourn_src->socid;
+ $sql .= ", '".$this->db->idate($now)."'";
+ $sql .= ', ' . (int) $this->suspended;
+ if (!empty(GETPOST('libelle'))) {
+ $sql .= ", '" . $this->db->escape(GETPOST('libelle')) . "'";
+ } elseif (! empty($this->libelle)) {
+ $sql .= ", '" . $this->db->escape($this->libelle) . "'";
+ } else {
+ $sql .= ", ''";
+ }
+ $sql .= ', ' .(!empty($facfourn_src->total_ttc) ? (float) $facfourn_src->total_ttc : '0'); // amount
+ $sql .= ', ' .(!empty($facfourn_src->remise) ? (float) $facfourn_src->remise : '0');
+ $sql .= ', ' . (int) $user->id;
+ $sql .= ', ' .(!empty($this->fk_project) ? $this->fk_project : 'NULL'); // Fields declarded on creation
+ $sql .= ', ' .(!empty($facfourn_src->fk_account) ? $facfourn_src->fk_account : 'NULL');
+ $sql .= ', ' .($this->cond_reglement_id > 0 ? (int) $this->cond_reglement_id : 'NULL');
+ $sql .= ', ' .($this->mode_reglement_id > 0 ? (int) $this->mode_reglement_id : 'NULL');
+ $sql .= ", '".($facfourn_src->date_echeance > 0 ? $this->db->idate($facfourn_src->date_echeance) : 'NULL')."'"; // date_lim_reglement
+ $sql .= ', ' .(!empty($this->note_private) ? "'".$this->db->escape($this->note_private)."'" : 'NULL'); // Fields declarded on creation
+ $sql .= ', ' .(!empty($this->note_public) ? "'".$this->db->escape($this->note_public)."'" : 'NULL'); // Fields declarded on creation
+ $sql .= ', ' .(!empty($this->model_pdf) ? "'".$this->db->escape($this->model_pdf)."'" : 'NULL'); // Fields declarded on creation
+ $sql .= ', ' . (int) $facfourn_src->fk_multicurrency;
+ $sql .= ", '".$this->db->escape($facfourn_src->multicurrency_code)."'";
+ $sql .= ', ' . (float) $facfourn_src->multicurrency_tx;
+ $sql .= ', ' . (int) $this->usenewprice; // Fields declarded on creation
+ $sql .= ', ' . (int) $this->frequency; // Fields declarded on creation
+ $sql .= ", '".$this->db->escape($this->unit_frequency)."'"; // Fields declarded on creation
+ $sql .= ', ' .(!empty($this->date_when) ? "'".$this->db->idate($this->date_when)."'" : 'NULL'); // Fields declarded on creation
+ $sql .= ', ' .(!empty($this->date_last_gen) ? "'".$this->db->idate($this->date_last_gen)."'" : 'NULL'); // Fields declarded on creation
+ $sql .= ', ' . (int) $this->nb_gen_done; // Fields declarded on creation
+ $sql .= ', ' . (int) $this->nb_gen_max; // Fields declarded on creation
+ $sql .= ', ' . (int) $this->auto_validate; // Fields declarded on creation
+ $sql .= ', ' . (int) $this->generate_pdf; // Fields declarded on creation
+ $sql .= ')';
+
+ if ($this->db->query($sql)) {
+ $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX. 'facture_fourn_rec');
+
+ // Fields used into addline later
+ $this->fk_multicurrency = $facfourn_src->fk_multicurrency;
+
+ $this->multicurrency_code = $facfourn_src->multicurrency_code;
+ $this->multicurrency_tx = $facfourn_src->multicurrency_tx;
+
+ // Add lines
+ $num = count($facfourn_src->lines);
+ for ($i = 0; $i < $num; $i++) {
+ $tva_tx = $facfourn_src->lines[$i]->tva_tx;
+ if (!empty($facfourn_src->lines[$i]->vat_src_code) && !preg_match('/\(/', $tva_tx)) {
+ $tva_tx .= ' ('.$facfourn_src->lines[$i]->vat_src_code.')';
+ }
+
+ $result_insert = $this->addline(
+ $facfourn_src->lines[$i]->fk_product,
+ $facfourn_src->lines[$i]->ref_supplier,
+ $facfourn_src->lines[$i]->label,
+ $facfourn_src->lines[$i]->description,
+ $facfourn_src->lines[$i]->pu_ht,
+ $facfourn_src->lines[$i]->pu_ttc,
+ $facfourn_src->lines[$i]->qty,
+ $facfourn_src->lines[$i]->remise_percent,
+ $tva_tx,
+ $facfourn_src->lines[$i]->localtax1_tx,
+ $facfourn_src->lines[$i]->localtax2_tx,
+ 'HT',
+ $facfourn_src->lines[$i]->product_type,
+ $facfourn_src->lines[$i]->date_start,
+ $facfourn_src->lines[$i]->date_end,
+ $facfourn_src->lines[$i]->info_bits,
+ $facfourn_src->lines[$i]->special_code,
+ $facfourn_src->lines[$i]->rang,
+ $facfourn_src->lines[$i]->fk_unit
+ );
+
+ if ($result_insert < 0) {
+ $error++;
+ } else {
+ $objectline = new FactureFournisseurLigneRec($this->db);
+
+ $result2 = $objectline->fetch($result_insert);
+ if ($result2 > 0) {
+ // Extrafields
+ if (method_exists($facfourn_src->lines[$i], 'fetch_optionals')) {
+ $facfourn_src->lines[$i]->fetch_optionals($facfourn_src->lines[$i]->id);
+ $objectline->array_options = $facfourn_src->lines[$i]->array_options;
+ }
+
+ $result = $objectline->insertExtraFields();
+ if ($result < 0) {
+ $error++;
+ }
+ } elseif ($result2 < 0) {
+ $this->errors[] = $objectline->error;
+ $error++;
+ }
+ }
+ }
+
+ if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) { // To use new linkedObjectsIds instead of old linked_objects
+ $this->linked_objects = $this->linkedObjectsIds; // TODO Replace linked_objects with linkedObjectsIds
+ }
+
+ // Add object linked
+ if (!$error && $this->id && !empty($this->linked_objects) && is_array($this->linked_objects)) {
+ foreach ($this->linked_objects as $origin => $tmp_origin_id) {
+ if (is_array($tmp_origin_id)) { // New behaviour, if linked_object can have several links per type, so is something like array('contract'=>array(id1, id2, ...))
+ foreach ($tmp_origin_id as $origin_id) {
+ $ret = $this->add_object_linked($origin, $origin_id);
+ if (!$ret) {
+ $this->error = $this->db->lasterror();
+ $error++;
+ }
+ }
+ } else // Old behaviour, if linked_object has only one link per type, so is something like array('contract'=>id1))
+ {
+ $origin_id = $tmp_origin_id;
+ $ret = $this->add_object_linked($origin, $origin_id);
+ if (!$ret) {
+ $this->error = $this->db->lasterror();
+ $error++;
+ }
+ }
+ }
+ }
+
+ if (!$error) {
+ $result = $this->insertExtraFields();
+ if ($result < 0) {
+ $error++;
+ }
+ }
+
+ if (!$error && !$notrigger) {
+ // Call trigger
+ $result = $this->call_trigger('SUPPLIERBILLREC_CREATE', $user);
+ if ($result < 0) {
+ $this->db->rollback();
+ return -2;
+ }
+ // End call triggers
+ }
+
+ if ($error) {
+ $this->db->rollback();
+ return -3;
+ } else {
+ $this->db->commit();
+ return $this->id;
+ }
+ } else {
+ $this->error = $this->db->lasterror();
+ $this->db->rollback();
+ return -2;
+ }
+ } else {
+ $this->db->rollback();
+ return -1;
+ }
+ }
+
+
+ /**
+ * Update fourn_invoice_rec.
+ *
+ * @param User $user User
+ * @param int $notrigger No trigger
+ * @return int <0 if KO, Id of line if OK
+ */
+ public function update(User $user, $notrigger = 0)
+ {
+ global $conf;
+
+ $error = 0;
+
+ $sql = "UPDATE ".MAIN_DB_PREFIX."facture_fourn_rec SET";
+ $sql .= ' titre = "' . (!empty($this->titre) ? $this->titre .'",' : '"",') ;
+ $sql .= ' ref_supplier = "'. (!empty($this->ref_supplier) ? $this->ref_supplier .'",' : '" ",');
+ $sql .= " entity = ". (!empty($this->entity) ? $this->entity : 1) . ',';
+ if ($this->fk_soc > 0) $sql .= " fk_soc = ". (int) $this->fk_soc. ',';
+ $sql .= ' tms = "'. date('Y-m-d H:i:s', dol_now()) . '",';
+ $sql .= " suspended = ". (!empty($this->suspended) ? $this->suspended : 0) . ',';
+ $sql .= ' libelle = "'. (!empty($this->libelle) ? $this->libelle : 'NULL') . '",';
+ $sql .= " amount = ". (!empty($this->amount) ? $this->amount : 0.00) . ',';
+ $sql .= " remise = ". (!empty($this->remise) ? $this->remise : 'NULL') . ',';
+ $sql .= " vat_src_code = ". (!empty($this->vat_src_code) ? $this->vat_src_code : 'NULL') . ',';
+ $sql .= " localtax1 = ". (!empty($this->localtax1) ? $this->localtax1 : 0.00) . ',';
+ $sql .= " localtax2 = ". (!empty($this->localtax2) ? $this->localtax2 : 0.00) . ',';
+ $sql .= " total_ht = ". (!empty($this->total_ht) ? $this->total_ht : 0.00) . ',';
+ $sql .= " total_tva = ". (!empty($this->total_tva) ? $this->total_tva : 0.00) . ',';
+ $sql .= " total_ttc = ". (!empty($this->total_ttc) ? $this->total_ttc : 0.00) . ',';
+ $sql .= " fk_user_modif = ". $user->id . ',';
+ $sql .= " fk_projet = ". (!empty($this->fk_project) ? $this->fk_project : 'NULL') . ',';
+ $sql .= " fk_account = ". (!empty($this->fk_account) ? $this->fk_account : 'NULL') . ',';
+ $sql .= " fk_mode_reglement = ". (!empty($this->mode_reglement_id) ? $this->mode_reglement_id : 'NULL') . ',';
+ $sql .= " fk_cond_reglement = ". (!empty($this->cond_reglement_id) ? $this->cond_reglement_id : 'NULL') . ',';
+ $sql .= " date_lim_reglement = ". (!empty($this->date_lim_reglement) ? '"'.date("Y-m-d H:i:s", $this->date_lim_reglement).'"' : 'NULL') . ',';
+ $sql .= ' note_private = "'. (!empty($this->note_private) ? $this->note_private : '') . '",';
+ $sql .= ' note_public = "'. (!empty($this->note_public) ? $this->note_public : '') . '",';
+ $sql .= ' modelpdf = "'. (!empty($this->model_pdf) ? $this->model_pdf : 'NULL') . '",';
+ $sql .= " fk_multicurrency = ". (!empty($this->fk_multicurrency) ? $this->fk_multicurrency : 'NULL') . ',';
+ $sql .= ' multicurrency_code = "'. (!empty($this->multicurrency_code) ? $this->multicurrency_code : 'NULL') . '",';
+ $sql .= " multicurrency_tx = ". (!empty($this->multicurrency_tx) ? $this->multicurrency_tx : 1) . ',';
+ $sql .= " multicurrency_total_ht = ". (!empty($this->multicurrency_total_ht) ? $this->multicurrency_total_ht : 0.00) . ',';
+ $sql .= " multicurrency_total_tva = ". (!empty($this->multicurrency_total_tva) ? $this->multicurrency_total_tva : 0.00) . ',';
+ $sql .= " multicurrency_total_ttc = ". (!empty($this->multicurrency_total_ttc) ? $this->multicurrency_total_ttc : 0.00) . ',';
+ $sql .= " usenewprice = ". (!empty($this->usenewprice) ? $this->usenewprice : 0) . ',';
+ $sql .= " frequency = ". (!empty($this->frequency) ? $this->frequency : 0). ',';
+ $sql .= ' unit_frequency = "'. (!empty($this->unit_frequency) ? $this->unit_frequency : 0). '",';
+ $sql .= " date_when = ". (!empty($this->date_when) ? '"'.date("Y-m-d H:i:s", $this->date_when).'"' : 0) . ',';
+ $sql .= " date_last_gen = ". (!empty($this->date_last_gen) ? '"'.date("Y-m-d H:i:s", $this->date_last_gen).'"' : 0) . ',';
+ $sql .= " nb_gen_done = ". (!empty($this->nb_gen_done) ? $this->nb_gen_done : 0) . ',';
+ $sql .= " nb_gen_max = ". (!empty($this->nb_gen_max) ? $this->nb_gen_max : 0) . ',';
+ $sql .= " auto_validate = ". (!empty($this->auto_validate) ? $this->auto_validate : 0);
+ $sql .= " WHERE rowid = ". (int) $this->id;
+
+ dol_syslog(get_class($this)."::update", LOG_DEBUG);
+ $resql = $this->db->query($sql);
+ if ($resql) {
+ if (!$error) {
+ $result = $this->insertExtraFields();
+ if ($result < 0) {
+ $error++;
+ }
+ }
+
+ if (!$error && !$notrigger) {
+ // Call trigger
+ $result = $this->call_trigger('BILLREC_UPDATE', $user);
+ if ($result < 0) {
+ $this->db->rollback();
+ return -2;
+ }
+ // End call triggers
+ }
+ $this->db->commit();
+ return 1;
+ } else {
+ $this->error = $this->db->lasterror();
+ $this->db->rollback();
+ return -2;
+ }
+ }
+
+ /**
+ * Load object and lines
+ *
+ * @param int $rowid Id of object to load
+ * @param string $ref Reference of recurring invoice
+ * @param string $ref_ext External reference of invoice
+ * @return int >0 if OK, <0 if KO, 0 if not found
+ */
+ public function fetch($rowid, $ref = '', $ref_ext = '')
+ {
+ $sql = 'SELECT f.rowid, f.titre, f.ref_supplier, f.entity, f.fk_soc';
+ $sql .= ', f.datec, f.tms, f.suspended';
+ $sql .= ', f.libelle, f.amount, f.remise';
+ $sql .= ', f.vat_src_code, f.localtax1, f.localtax2';
+ $sql .= ', f.total_tva, f.total_ht, f.total_ttc';
+ $sql .= ', f.fk_user_author, f.fk_user_modif';
+ $sql .= ', f.fk_projet, f.fk_account';
+ $sql .= ', f.fk_mode_reglement, p.code as mode_reglement_code, p.libelle as mode_reglement_libelle';
+ $sql .= ', f.fk_cond_reglement, c.code as cond_reglement_code, c.libelle as cond_reglement_libelle, c.libelle_facture as cond_reglement_libelle_doc';
+ $sql .= ', f.date_lim_reglement';
+ $sql .= ', f.note_private, f.note_public, f.modelpdf';
+ $sql .= ', f.fk_multicurrency, f.multicurrency_code, f.multicurrency_tx, f.multicurrency_total_ht, f.multicurrency_total_tva, f.multicurrency_total_ttc';
+ $sql .= ', f.usenewprice, f.frequency, f.unit_frequency, f.date_when, f.date_last_gen, f.nb_gen_done, f.nb_gen_max, f.auto_validate';
+ $sql .= ', f.generate_pdf';
+ $sql .= ' FROM '.MAIN_DB_PREFIX.'facture_fourn_rec as f';
+ $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_payment_term as c ON f.fk_cond_reglement = c.rowid';
+ $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as p ON f.fk_mode_reglement = p.id';
+ $sql .= ' WHERE f.entity IN ('.getEntity('invoice').')';
+ if ($rowid) {
+ $sql .= ' AND f.rowid='. (int) $rowid;
+ } elseif ($ref) {
+ $sql .= " AND f.titre='".$this->db->escape($ref)."'";
+ } else {
+ $sql .= ' AND f.rowid = 0';
+ }
+
+ $result = $this->db->query($sql);
+ if ($result) {
+ if ($this->db->num_rows($result)) {
+ $obj = $this->db->fetch_object($result);
+
+ $this->id = $obj->rowid;
+ $this->titre = $obj->titre;
+ $this->ref_supplier = $obj->ref_supplier;
+ $this->entity = $obj->entity;
+ $this->socid = $obj->fk_soc;
+ $this->date_creation = $obj->datec;
+ $this->date_modification = $obj->tms;
+ $this->suspended = $obj->suspended;
+ $this->libelle = $obj->libelle;
+ $this->amount = $obj->amount;
+ $this->remise = $obj->remise;
+ $this->vat_src_code = $obj->vat_src_code;
+ $this->total_localtax1 = $obj->localtax1;
+ $this->total_localtax2 = $obj->localtax2;
+ $this->total_ht = $obj->total_ht;
+ $this->total_tva = $obj->total_tva;
+ $this->total_ttc = $obj->total_ttc;
+ $this->user_author = $obj->fk_user_author;
+ $this->user_modif = $obj->fk_user_modif;
+ $this->fk_project = $obj->fk_projet;
+ $this->fk_account = $obj->fk_account;
+ $this->mode_reglement_id = $obj->fk_mode_reglement;
+ $this->mode_reglement_code = $obj->mode_reglement_code;
+ $this->mode_reglement = $obj->mode_reglement_libelle;
+ $this->cond_reglement_id = $obj->fk_cond_reglement;
+ $this->cond_reglement_code = $obj->cond_reglement_code;
+ $this->cond_reglement = $obj->cond_reglement_libelle;
+ $this->cond_reglement_doc = $obj->cond_reglement_libelle_doc;
+ $this->date_lim_reglement = $this->db->jdate($obj->date_lim_reglement);
+ $this->note_private = $obj->note_private;
+ $this->note_public = $obj->note_public;
+ $this->model_pdf = $obj->modelpdf;
+
+ // Multicurrency
+ $this->fk_multicurrency = $obj->fk_multicurrency;
+ $this->multicurrency_code = $obj->multicurrency_code;
+ $this->multicurrency_tx = $obj->multicurrency_tx;
+ $this->multicurrency_total_ht = $obj->multicurrency_total_ht;
+ $this->multicurrency_total_tva = $obj->multicurrency_total_tva;
+ $this->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
+
+ $this->usenewprice = $obj->usenewprice;
+ $this->frequency = $obj->frequency;
+ $this->unit_frequency = $obj->unit_frequency;
+ $this->date_when = $this->db->jdate($obj->date_when);
+ $this->date_last_gen = $this->db->jdate($obj->date_last_gen);
+ $this->nb_gen_done = $obj->nb_gen_done;
+ $this->nb_gen_max = $obj->nb_gen_max;
+ $this->auto_validate = $obj->auto_validate;
+ $this->generate_pdf = $obj->generate_pdf;
+
+
+ if ($this->statut == self::STATUS_DRAFT) {
+ $this->brouillon = 1;
+ }
+
+ // Retrieve all extrafield
+ // fetch optionals attributes and labels
+ $this->fetch_optionals();
+
+ /*
+ * Lines
+ */
+ $result = $this->fetch_lines();
+ if ($result < 0) {
+ $this->error = $this->db->lasterror();
+ return -3;
+ }
+ return 1;
+ } else {
+ $this->error = 'Bill with id '.$rowid.' or ref '.$ref.' not found';
+ dol_syslog('Facture::Fetch Error '.$this->error, LOG_ERR);
+ return -2;
+ }
+ } else {
+ $this->error = $this->db->error();
+ return -1;
+ }
+ }
+
+
+ /**
+ * Create an array of invoice lines
+ *
+ * @return int >0 if OK, <0 if KO
+ */
+ public function getLinesArray()
+ {
+ return $this->fetch_lines();
+ }
+
+
+ // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+ /**
+ * Get lines of template invoices into this->lines
+ *
+ * @return int 1 if OK, < 0 if KO
+ */
+ public function fetch_lines()
+ {
+ global $extrafields;
+
+ // phpcs:enable
+ $this->lines = array();
+
+ // Retrieve all extrafield for line
+ // fetch optionals attributes and labels
+ if (!is_object($extrafields)) {
+ require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
+ $extrafields = new ExtraFields($this->db);
+ }
+ $extrafields->fetch_name_optionals_label($this->table_element_line, true);
+
+ $sql = 'SELECT l.rowid,';
+ $sql .= ' l.fk_facture_fourn, l.fk_parent_line, l.fk_product, l.ref, l.label, l.description,';
+ $sql .= ' l.pu_ht, l.pu_ttc, l.qty, l.remise_percent, l.fk_remise_except, l.vat_src_code, l.tva_tx,';
+ $sql .= ' l.localtax1_tx, l.localtax2_tx, l.localtax1_type, l.localtax2_type,';
+ $sql .= ' l.total_ht, l.total_tva, l.total_ttc, total_localtax1, total_localtax2,';
+ $sql .= ' l.product_type, l.date_start, l.date_end,';
+ $sql .= ' l.info_bits, l.special_code, l.rang,';
+ $sql .= ' l.fk_unit, l.import_key, l.fk_user_author, l.fk_user_modif,';
+ $sql .= ' l.fk_multicurrency, l.multicurrency_code, l.multicurrency_subprice, l.multicurrency_total_ht, l.multicurrency_total_tva, l.multicurrency_total_ttc,';
+ $sql .= ' p.ref as product_ref, p.fk_product_type as fk_product_type, p.label as product_label, p.description as product_desc';
+ $sql .= ' FROM '.MAIN_DB_PREFIX.'facture_fourn_det_rec as l';
+ $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON l.fk_product = p.rowid';
+ $sql .= ' WHERE l.fk_facture_fourn = '. (int) $this->id;
+ $sql .= ' ORDER BY l.rang';
+
+ dol_syslog('FactureFournisseurRec::fetch_lines', LOG_DEBUG);
+ $result = $this->db->query($sql);
+ if ($result) {
+ $num = $this->db->num_rows($result);
+ $i = 0;
+ while ($i < $num) {
+ $objp = $this->db->fetch_object($result);
+ $line = new FactureFournisseurLigneRec($this->db);
+
+ $line->id = $objp->rowid;
+ $line->fk_facture_fourn = $objp->fk_facture_fourn;
+ $line->fk_parent = $objp->fk_parent_line;
+ $line->fk_product = $objp->fk_product;
+ $line->ref_supplier = $objp->ref;
+ $line->label = $objp->label;
+ $line->description = $objp->description;
+ $line->pu_ht = $objp->pu_ht;
+ $line->pu_ttc = $objp->pu_ttc;
+ $line->qty = $objp->qty;
+ $line->remise_percent = $objp->remise_percent;
+ $line->fk_remise_except = $objp->fk_remise_except;
+ $line->vat_src_code = $objp->vat_src_code;
+ $line->tva_tx = $objp->tva_tx;
+ $line->localtax1_tx = $objp->localtax1_tx;
+ $line->localtax1_type = $objp->localtax1_type;
+ $line->localtax2_tx = $objp->localtax2_tx;
+ $line->localtax2_type = $objp->localtax2_type;
+ $line->total_ht = $objp->total_ht;
+ $line->total_tva = $objp->total_tva;
+ $line->total_localtax1 = $objp->total_localtax1;
+ $line->total_localtax2 = $objp->total_localtax2;
+ $line->total_ttc = $objp->total_ttc;
+ $line->product_type = $objp->product_type;
+ $line->date_start = $objp->date_start;
+ $line->date_end = $objp->date_end;
+ $line->info_bits = $objp->info_bits ;
+ $line->special_code = $objp->special_code;
+ $line->rang = $objp->rang;
+ $line->fk_unit = $objp->fk_unit;
+ $line->import_key = $objp->import_key;
+ $line->fk_user_author = $objp->fk_user_author;
+ $line->fk_user_modif = $objp->fk_user_modif;
+ $line->fk_multicurrency = $objp->fk_multicurrency;
+ $line->multicurrency_code = $objp->multicurrency_code;
+ $line->multicurrency_subprice = $objp->multicurrency_subprice;
+ $line->multicurrency_total_ht = $objp->multicurrency_total_ht;
+ $line->multicurrency_total_tva = $objp->multicurrency_total_tva;
+ $line->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
+
+ $line->fetch_optionals();
+
+ $this->lines[$i] = $line;
+
+ $i++;
+ }
+
+ $this->db->free($result);
+ return 1;
+ } else {
+ $this->error = $this->db->lasterror();
+ return -3;
+ }
+ }
+
+
+ /**
+ * Delete template invoice
+ *
+ * @param User $user User that delete.
+ * @param int $notrigger 1=Does not execute triggers, 0= execute triggers
+ * @param int $idwarehouse Id warehouse to use for stock change.
+ * @return int <0 if KO, >0 if OK
+ */
+ public function delete(User $user, $notrigger = 0, $idwarehouse = -1)
+ {
+ $rowid = $this->id;
+
+ dol_syslog(get_class($this)."::delete rowid=".((int) $rowid), LOG_DEBUG);
+
+ $error = 0;
+ $this->db->begin();
+
+ $main = MAIN_DB_PREFIX.'facture_fourn_det_rec';
+ $ef = $main."_extrafields";
+
+ $sqlef = "DELETE FROM ".$ef." WHERE fk_object IN (SELECT rowid FROM ".$main." WHERE fk_facture_fourn = ". (int) $rowid .")";
+ $sql = "DELETE FROM ".MAIN_DB_PREFIX."facture_fourn_det_rec WHERE fk_facture_fourn = ". (int) $rowid;
+
+ if ($this->db->query($sqlef) && $this->db->query($sql)) {
+ $sql = "DELETE FROM ".MAIN_DB_PREFIX."facture_fourn_rec WHERE rowid = ". (int) $rowid;
+ dol_syslog($sql);
+ if ($this->db->query($sql)) {
+ // Delete linked object
+ $res = $this->deleteObjectLinked();
+ if ($res < 0) {
+ $error = -3;
+ }
+ // Delete extrafields
+ $res = $this->deleteExtraFields();
+ if ($res < 0) {
+ $error = -4;
+ }
+ } else {
+ $this->error = $this->db->lasterror();
+ $error = -1;
+ }
+ } else {
+ $this->error = $this->db->lasterror();
+ $error = -2;
+ }
+
+ if (!$error) {
+ $this->db->commit();
+ return 1;
+ } else {
+ $this->db->rollback();
+ return $error;
+ }
+ }
+
+ /**
+ * Add a line to recursive supplier invoice
+ *
+ * @param int $fk_product Product/Service ID predefined
+ * @param string $ref Ref
+ * @param string $label Label
+ * @param string $desc Description de la ligne
+ * @param double $pu_ht Unit price
+ * @param double $pu_ttc Unit price with tax
+ * @param double $qty Quantity
+ * @param int $remise_percent Percentage discount of the line
+ * @param double $txtva Taux de tva force, sinon -1
+ * @param int $txlocaltax1 Local tax 1 rate (deprecated)
+ * @param int $txlocaltax2 Local tax 2 rate (deprecated)
+ * @param string $price_base_type HT or TTC
+ * @param int $type Type of line (0=product, 1=service)
+ * @param int $date_start Date start
+ * @param int $date_end Date end
+ * @param int $info_bits VAT npr or not ?
+ * @param int $special_code Special code
+ * @param int $rang Position of line
+ * @param string $fk_unit Unit
+ * @param int $pu_ht_devise Unit price in currency
+ * @return int <0 if KO, Id of line if OK
+ * @throws Exception
+ */
+ public function addline($fk_product, $ref, $label, $desc, $pu_ht, $pu_ttc, $qty, $remise_percent, $txtva, $txlocaltax1 = 0, $txlocaltax2 = 0, $price_base_type = 'HT', $type = 0, $date_start = 0, $date_end = 0, $info_bits = 0, $special_code = 0, $rang = -1, $fk_unit = null, $pu_ht_devise = 0)
+ {
+ global $mysoc, $user;
+
+ include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
+
+ $facid = $this->id; //Supplier invoice template ID linked to
+
+ dol_syslog(get_class($this)."::addline facid=$facid,desc=$desc,pu_ht=$pu_ht,qty=$qty,txtva=$txtva,txlocaltax1=$txlocaltax1,txlocaltax2=$txlocaltax2,fk_product=$fk_product,remise_percent=$remise_percent,info_bits=$info_bits,price_base_type=$price_base_type,pu_ttc=$pu_ttc,type=$type,fk_unit=$fk_unit,pu_ht_devise=$pu_ht_devise,date_start_fill=$date_start,date_end_fill=$date_end", LOG_DEBUG);
+
+ // Check if object of the line is product or service
+ if ($type < 0) {
+ return -1;
+ }
+
+ if ($this->suspended == self::STATUS_NOTSUSPENDED) {
+ $localtaxes_type = getLocalTaxesFromRate($txtva, 0, $this->thirdparty, $mysoc);
+
+ // Clean vat code
+ $reg = array();
+ $vat_src_code = '';
+ if (preg_match('/\((.*)\)/', $txtva, $reg)) {
+ $vat_src_code = $reg[1];
+ $txtva = preg_replace('/\s*\(.*\)/', '', $txtva); // Remove code into vatrate.
+ }
+
+ // Clean parameters
+ $fk_product = empty($fk_product) ? 0 : $fk_product;
+ $label = empty($label) ? '' : $label;
+ $remise_percent = empty($remise_percent) ? 0 : price2num($remise_percent);
+ $qty = price2num($qty);
+ $pu_ht = price2num($pu_ht);
+ $pu_ttc = price2num($pu_ttc);
+ if (!preg_match('/\((.*)\)/', $txtva)) {
+ $txtva = price2num($txtva); // $txtva can have format '5.0(XXX)' or '5'
+ }
+ $txlocaltax1 = price2num($txlocaltax1);
+ $txlocaltax2 = price2num($txlocaltax2);
+ $txtva = !empty($txtva) ? $txtva : 0;
+ $txlocaltax1 = !empty($txlocaltax1) ? $txlocaltax1 : 0;
+ $txlocaltax2 = !empty($txlocaltax2) ? $txlocaltax2 : 0;
+ $info_bits = !empty($info_bits) ? $info_bits : 0;
+ $info_bits = !empty($info_bits) ? $info_bits : 0;
+ $pu = $price_base_type == 'HT' ? $pu_ht : $pu_ttc;
+
+ // Calcul du total TTC et de la TVA pour la ligne a partir de qty, pu, remise_percent et txtva
+ // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
+ // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
+
+ $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise);
+ $total_ht = $tabprice[0];
+ $total_tva = $tabprice[1];
+ $total_ttc = $tabprice[2];
+ $total_localtax1 = $tabprice[9];
+ $total_localtax2 = $tabprice[10];
+ $pu_ht = $tabprice[3];
+
+ // MultiCurrency
+ $multicurrency_total_ht = $tabprice[16];
+ $multicurrency_total_tva = $tabprice[17];
+ $multicurrency_total_ttc = $tabprice[18];
+ $pu_ht_devise = $tabprice[19];
+
+ $this->db->begin();
+ $product_type = $type;
+ if ($fk_product) {
+ $product = new Product($this->db);
+ $result = $product->fetch($fk_product);
+ if ($result < 0) {
+ return -1;
+ }
+ $product_type = $product->type;
+ if (empty($label)) {
+ $label = $product->label;
+ }
+ }
+
+ $sql = 'INSERT INTO ' . MAIN_DB_PREFIX . 'facture_fourn_det_rec (';
+ $sql .= 'fk_facture_fourn';
+ $sql .= ', fk_product';
+ $sql .= ', ref';
+ $sql .= ', label';
+ $sql .= ', description';
+ $sql .= ', pu_ht';
+ $sql .= ', pu_ttc';
+ $sql .= ', qty';
+ $sql .= ', remise_percent';
+ $sql .= ', fk_remise_except';
+ $sql .= ', vat_src_code';
+ $sql .= ', tva_tx';
+ $sql .= ', localtax1_tx';
+ $sql .= ', localtax1_type';
+ $sql .= ', localtax2_tx';
+ $sql .= ', localtax2_type';
+ $sql .= ', total_ht';
+ $sql .= ', total_tva';
+ $sql .= ', total_localtax1';
+ $sql .= ', total_localtax2';
+ $sql .= ', total_ttc';
+ $sql .= ', product_type';
+ $sql .= ', date_start';
+ $sql .= ', date_end';
+ $sql .= ', info_bits';
+ $sql .= ', special_code';
+ $sql .= ', rang';
+ $sql .= ', fk_unit';
+ $sql .= ', fk_user_author';
+ $sql .= ', fk_multicurrency, multicurrency_code, multicurrency_subprice, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc';
+ $sql .= ') VALUES (';
+ $sql .= ' ' . (int) $facid; // source supplier invoie id
+ $sql .= ', ' . (! empty($fk_product) ? "'" . $this->db->escape($fk_product) . "'" : 'null');
+ $sql .= ', ' . (! empty($ref) ? "'" . $this->db->escape($ref) . "'" : 'null');
+ $sql .= ', ' . (! empty($label) ? "'" . $this->db->escape($label) . "'" : 'null');
+ $sql .= ", '" . $this->db->escape($desc) . "'";
+ $sql .= ', ' . price2num($pu_ht);
+ $sql .= ', ' . price2num($pu_ttc);
+ $sql .= ', ' . price2num($qty);
+ $sql .= ', ' . price2num($remise_percent);
+ $sql .= ', null';
+ $sql .= ", '" . $this->db->escape($vat_src_code) . "'";
+ $sql .= ', ' . price2num($txtva);
+ $sql .= ', ' . price2num($txlocaltax1);
+ $sql .= ", '" . $this->db->escape(isset($localtaxes_type[0]) ? $localtaxes_type[0] : '') . "'";
+ $sql .= ', ' . price2num($txlocaltax2);
+ $sql .= ", '" . $this->db->escape(isset($localtaxes_type[2]) ? $localtaxes_type[2] : '') . "'";
+ $sql .= ', ' . price2num($total_ht);
+ $sql .= ', ' . price2num($total_tva);
+ $sql .= ', ' . price2num($total_localtax1);
+ $sql .= ', ' . price2num($total_localtax2);
+ $sql .= ', ' . price2num($total_ttc);
+ $sql .= ', ' . (int) $product_type;
+ $sql .= ', ' . ($date_start > 0 ? (int) $date_start : 'NULL');
+ $sql .= ', ' . ($date_end > 0 ? (int) $date_end : 'NULL');
+ $sql .= ', ' . (int) $info_bits;
+ $sql .= ', ' . (int) $special_code;
+ $sql .= ', ' . (int) $rang;
+ $sql .= ', ' . ($fk_unit ? (int) $fk_unit : 'NULL');
+ $sql .= ', ' . (int) $user;
+ $sql .= ', ' . (int) $this->fk_multicurrency;
+ $sql .= ", '" . $this->db->escape($this->multicurrency_code) . "'";
+ $sql .= ', ' . price2num($pu_ht_devise, 'CU');
+ $sql .= ', ' . price2num($multicurrency_total_ht, 'CT');
+ $sql .= ', ' . price2num($multicurrency_total_tva, 'CT');
+ $sql .= ', ' . price2num($multicurrency_total_ttc, 'CT');
+ $sql .= ')';
+
+ dol_syslog(get_class($this). '::addline', LOG_DEBUG);
+ if ($this->db->query($sql)) {
+ $lineId = $this->db->last_insert_id(MAIN_DB_PREFIX. 'facture_fourn_det_rec');
+ $this->update_price();
+ $this->id = $facid;
+ $this->db->commit();
+ return $lineId;
+ } else {
+ $this->db->rollback();
+ $this->error = $this->db->lasterror();
+
+ return -1;
+ }
+ }
+ }
+
+ /**
+ * Update a line to supplier invoice template
+ *
+ * @param $rowid ID
+ * @param int $fk_product Product/Service ID predefined
+ * @param $ref Ref
+ * @param string $label Label of the line
+ * @param string $desc Description de la ligne
+ * @param double $pu_ht Prix unitaire HT (> 0 even for credit note)
+ * @param double $qty Quantity
+ * @param int $remise_percent Percentage discount of the line
+ * @param double $txtva Taux de tva force, sinon -1
+ * @param int $txlocaltax1 Local tax 1 rate (deprecated)
+ * @param int $txlocaltax2 Local tax 2 rate (deprecated)
+ * @param string $price_base_type HT or TTC
+ * @param int $type Type of line (0=product, 1=service)
+ * @param int $date_start Date start
+ * @param int $date_end Date end
+ * @param int $info_bits Bits of type of lines
+ * @param int $special_code Special code
+ * @param int $rang Position of line
+ * @param string $fk_unit Unit
+ * @param int $pu_ht_devise Unit price in currency
+ * @return int <0 if KO, Id of line if OK
+ * @throws Exception
+ */
+ public function updateline($rowid, $fk_product, $ref, $label, $desc, $pu_ht, $qty, $remise_percent, $txtva, $txlocaltax1 = 0, $txlocaltax2 = 0, $price_base_type = 'HT', $type = 0, $date_start = 0, $date_end = 0, $info_bits = 0, $special_code = 0, $rang = -1, $fk_unit = null, $pu_ht_devise = 0)
+ {
+ global $mysoc, $user;
+
+ $facid = $this->id;
+
+ dol_syslog(get_class($this). '::updateline facid=' .$facid." rowid=$rowid, desc=$desc, pu_ht=$pu_ht, qty=$qty, txtva=$txtva, txlocaltax1=$txlocaltax1, txlocaltax2=$txlocaltax2, fk_product=$fk_product, remise_percent=$remise_percent, info_bits=$info_bits, fk_remise_except=$fk_remise_except, price_base_type=$price_base_type, pu_ttc=$pu_ttc, type=$type, fk_unit=$fk_unit, pu_ht_devise=$pu_ht_devise", LOG_DEBUG);
+ include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
+
+ // Check parameters
+ if ($type < 0) {
+ return -1;
+ }
+
+ if ($this->brouillon) {
+ // Clean parameters
+ $fk_product = empty($fk_product) ? 0 : $fk_product;
+ $label = empty($label) ? '' : $label;
+ $remise_percent = empty($remise_percent) ? 0 : price2num($remise_percent);
+ $qty = price2num($qty);
+ $info_bits = empty($info_bits) ? 0 : $info_bits;
+ $pu_ht = price2num($pu_ht);
+ $pu_ttc = price2num($pu_ttc);
+ $pu_ht_devise = price2num($pu_ht_devise);
+
+ if (!preg_match('/\((.*)\)/', $txtva)) {
+ $txtva = price2num($txtva); // $txtva can have format '5.0(XXX)' or '5'
+ }
+
+ $txlocaltax1 = empty($txlocaltax1) ? 0 : price2num($txlocaltax1);
+ $txlocaltax2 = empty($txlocaltax2) ? 0 : price2num($txlocaltax2);
+ $this->multicurrency_subprice = empty($this->multicurrency_subprice) ? 0 : $this->multicurrency_subprice;
+ $this->multicurrency_total_ht = empty($this->multicurrency_total_ht) ? 0 : $this->multicurrency_total_ht;
+ $this->multicurrency_total_tva = empty($this->multicurrency_total_tva) ? 0 : $this->multicurrency_total_tva;
+ $this->multicurrency_total_ttc = empty($this->multicurrency_total_ttc) ? 0 : $this->multicurrency_total_ttc;
+
+ $pu = $price_base_type == 'HT' ? $pu_ht : $pu_ttc;
+
+
+ // Calculate total with, without tax and tax from qty, pu, remise_percent and txtva
+ // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
+ // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
+
+ $localtaxes_type = getLocalTaxesFromRate($txtva, 0, $this->thirdparty, $mysoc);
+
+ // Clean vat code
+ $vat_src_code = '';
+ $reg = array();
+ if (preg_match('/\((.*)\)/', $txtva, $reg)) {
+ $vat_src_code = $reg[1];
+ $txtva = preg_replace('/\s*\(.*\)/', '', $txtva); // Remove code into vatrate.
+ }
+
+ $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise);
+
+ $total_ht = $tabprice[0];
+ $total_tva = $tabprice[1];
+ $total_ttc = $tabprice[2];
+ $total_localtax1 = $tabprice[9];
+ $total_localtax2 = $tabprice[10];
+ $pu_ht = $tabprice[3];
+ $pu_tva = $tabprice[4];
+ $pu_ttc = $tabprice[5];
+
+ // MultiCurrency
+ $multicurrency_total_ht = $tabprice[16];
+ $multicurrency_total_tva = $tabprice[17];
+ $multicurrency_total_ttc = $tabprice[18];
+ $pu_ht_devise = $tabprice[19];
+
+ $product_type = $type;
+ if ($fk_product) {
+ $product = new Product($this->db);
+ $result = $product->fetch($fk_product);
+ $product_type = $product->type;
+ }
+
+ $sql = 'UPDATE ' . MAIN_DB_PREFIX . 'facture_fourn_det_rec SET';
+ $sql .= ' fk_facture_fourn = ' . ((int) $facid);
+ $sql .= ', fk_product = ' . ($fk_product > 0 ? ((int) $fk_product) : 'null');
+ $sql .= ", ref = '" . $this->db->escape($ref) . "'";
+ $sql .= ", label = '" . $this->db->escape($label) . "'";
+ $sql .= ", description = '" . $this->db->escape($desc) . "'";
+ $sql .= ', pu_ht=' . price2num($pu_ht);
+ $sql .= ', qty=' . price2num($qty);
+ $sql .= ", remise_percent='" . price2num($remise_percent) . "'";
+ $sql .= ", vat_src_code='" . $this->db->escape($vat_src_code) . "'";
+ $sql .= ', tva_tx=' . price2num($txtva);
+ $sql .= ', localtax1_tx=' . (float) $txlocaltax1;
+ $sql .= ", localtax1_type='" . $this->db->escape($localtaxes_type[0]) . "'";
+ $sql .= ', localtax2_tx=' . (float) $txlocaltax2;
+ $sql .= ", localtax2_type='" . $this->db->escape($localtaxes_type[2]) . "'";
+ $sql .= ", total_ht='" . price2num($total_ht) . "'";
+ $sql .= ", total_tva='" . price2num($total_tva) . "'";
+ $sql .= ", total_localtax1='" . price2num($total_localtax1) . "'";
+ $sql .= ", total_localtax2='" . price2num($total_localtax2) . "'";
+ $sql .= ", total_ttc='" . price2num($total_ttc) . "'";
+ $sql .= ', product_type=' . (int) $product_type;
+ $sql .= ', date_start=' . (empty($date_start) ? 'NULL' : (int) $date_start);
+ $sql .= ', date_end=' . (empty($date_end) ? 'NULL' : (int) $date_end);
+ $sql .= ', info_bits=' . (int) $info_bits;
+ $sql .= ', special_code=' . (int) $special_code;
+ $sql .= ', rang=' . (int) $rang;
+ $sql .= ', fk_unit=' . ($fk_unit ? "'" . $this->db->escape($fk_unit) . "'" : 'null');
+ $sql .= ', fk_user_modif=' . (int) $user;
+ $sql .= ', multicurrency_subprice = '.price2num($pu_ht_devise);
+ $sql .= ', multicurrency_total_ht = '.price2num($multicurrency_total_ht);
+ $sql .= ', multicurrency_total_tva = '.price2num($multicurrency_total_tva);
+ $sql .= ', multicurrency_total_ttc = '.price2num($multicurrency_total_ttc);
+ $sql .= ' WHERE rowid = ' . (int) $rowid;
+
+ dol_syslog(get_class($this). '::updateline', LOG_DEBUG);
+ if ($this->db->query($sql)) {
+ $this->id = $facid;
+ $this->update_price();
+ return 1;
+ } else {
+ $this->error = $this->db->lasterror();
+ return -1;
+ }
+ }
+ }
+
+
+ /**
+ * Return the next date of
+ *
+ * @return int|false false if KO, timestamp if OK
+ */
+ public function getNextDate()
+ {
+ if (empty($this->date_when)) {
+ return false;
+ }
+ return dol_time_plus_duree($this->date_when, $this->frequency, $this->unit_frequency);
+ }
+
+ /**
+ * Return if maximum number of generation is reached
+ *
+ * @return boolean False by default, True if maximum number of generation is reached
+ */
+ public function isMaxNbGenReached()
+ {
+ $ret = false;
+ if ($this->nb_gen_max > 0 && ($this->nb_gen_done >= $this->nb_gen_max)) {
+ $ret = true;
+ }
+ return $ret;
+ }
+
+ /**
+ * Format string to output with by striking the string if max number of generation was reached
+ *
+ * @param string $ret Default value to output
+ * @return boolean False by default, True if maximum number of generation is reached
+ */
+ public function strikeIfMaxNbGenReached($ret)
+ {
+ // Special case to strike the date
+ return ($this->isMaxNbGenReached() ? '' : '').$ret.($this->isMaxNbGenReached() ? ' ' : '');
+ }
+
+ /**
+ * Create all recurrents supplier invoices (for all entities if multicompany is used).
+ * A result may also be provided into this->output.
+ *
+ * WARNING: This method change temporarly context $conf->entity to be in correct context for each recurring invoice found.
+ *
+ * @param int $restrictioninvoiceid 0=All qualified template invoices found. > 0 = restrict action on invoice ID
+ * @param int $forcevalidation 1=Force validation of invoice whatever is template auto_validate flag.
+ * @return int 0 if OK, < 0 if KO (this function is used also by cron so only 0 is OK)
+ */
+ public function createRecurringInvoices($restrictioninvoiceid = 0, $forcevalidation = 0)
+ {
+ global $conf, $langs, $db, $user, $hookmanager;
+
+ $error = 0;
+ $nb_create = 0;
+
+ // Load translation files required by the page
+ $langs->loadLangs(array('main', 'bills'));
+
+ $now = dol_now();
+ $tmparray = dol_getdate($now);
+ $today = dol_mktime(23, 59, 59, $tmparray['mon'], $tmparray['mday'], $tmparray['year']); // Today is last second of current day
+
+ dol_syslog('createRecurringInvoices restrictioninvoiceid=' .$restrictioninvoiceid. ' forcevalidation=' .$forcevalidation);
+
+ $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'facture_fourn_rec';
+ $sql .= ' WHERE frequency > 0'; // A recurring supplier invoice is an invoice with a frequency
+ $sql .= " AND (date_when IS NULL OR date_when <= '".$this->db->idate($today)."')";
+ $sql .= ' AND (nb_gen_done < nb_gen_max OR nb_gen_max = 0)';
+ $sql .= ' AND suspended = 0';
+ $sql .= ' AND entity = '. (int) $conf->entity; // MUST STAY = $conf->entity here
+ if ($restrictioninvoiceid > 0) {
+ $sql .= ' AND rowid = '. (int) $restrictioninvoiceid;
+ }
+ $sql .= $this->db->order('entity', 'ASC');
+ //print $sql;exit;
+ $parameters = array(
+ 'restrictioninvoiceid' => $restrictioninvoiceid,
+ 'forcevalidation' => $forcevalidation,
+ );
+ $reshook = $hookmanager->executeHooks('beforeCreationOfRecurringInvoices', $parameters, $sql); // note that $sql might be modified by hooks
+
+ $resql = $this->db->query($sql);
+ if ($resql) {
+ $i = 0;
+ $num = $this->db->num_rows($resql);
+
+ if ($num) {
+ $this->output .= $langs->trans('FoundXQualifiedRecurringInvoiceTemplate', $num)."\n";
+ } else {
+ $this->output .= $langs->trans('NoQualifiedRecurringInvoiceTemplateFound');
+ }
+
+ $saventity = $conf->entity;
+
+ while ($i < $num) { // Loop on each template invoice. If $num = 0, test is false at first pass.
+ $line = $this->db->fetch_object($resql);
+
+ $this->db->begin();
+
+ $invoiceidgenerated = 0;
+
+ $new_fac_fourn = null;
+ $facturerec = new FactureFournisseurRec($this->db);
+ $facturerec->fetch($line->rowid);
+
+ if ($facturerec->id > 0) {
+ // Set entity context
+ $conf->entity = $facturerec->entity;
+
+ dol_syslog('createRecurringInvoices Process invoice template id=' .$facturerec->id. ', ref=' .$facturerec->ref. ', entity=' .$facturerec->entity);
+
+ $new_fac_fourn = new FactureFournisseur($this->db);
+ $new_fac_fourn->fac_rec = $facturerec->id; // We will create $facture from this recurring invoice
+ $new_fac_fourn->fk_fac_rec_source = $facturerec->id; // We will create $facture from this recurring invoice
+
+ $new_fac_fourn->type = self::TYPE_STANDARD;
+ $new_fac_fourn->brouillon = 1;
+ $new_fac_fourn->statut = self::STATUS_DRAFT;
+ $new_fac_fourn->status = self::STATUS_DRAFT;
+ $new_fac_fourn->date = empty($facturerec->date_when) ? $now : $facturerec->date_when; // We could also use dol_now here but we prefer date_when so invoice has real date when we would like even if we generate later.
+ $new_fac_fourn->socid = $facturerec->socid;
+ $new_fac_fourn->lines = $facturerec->lines;
+ $new_fac_fourn->ref_supplier = $facturerec->ref_supplier;
+ $new_fac_fourn->model_pdf = $facturerec->model_pdf;
+ $new_fac_fourn->fk_project = $facturerec->fk_project;
+ $new_fac_fourn->libelle = $facturerec->libelle;
+
+ $invoiceidgenerated = $new_fac_fourn->create($user);
+ if ($invoiceidgenerated <= 0) {
+ $this->errors = $new_fac_fourn->errors;
+ $this->error = $new_fac_fourn->error;
+ $error++;
+ }
+ if (!$error && ($facturerec->auto_validate || $forcevalidation)) {
+ $result = $new_fac_fourn->validate($user);
+ if ($result <= 0) {
+ $this->errors = $new_fac_fourn->errors;
+ $this->error = $new_fac_fourn->error;
+ $error++;
+ }
+ }
+
+ if (!$error && $facturerec->generate_pdf) {
+ // We refresh the object in order to have all necessary data (like date_lim_reglement)
+ $new_fac_fourn->fetch($new_fac_fourn->id);
+ $result = $new_fac_fourn->generateDocument($facturerec->model_pdf, $langs);
+ if ($result <= 0) {
+ $this->errors = $new_fac_fourn->errors;
+ $this->error = $new_fac_fourn->error;
+ $error++;
+ }
+ }
+ } else {
+ $error++;
+ $this->error = 'Failed to load invoice template with id=' .$line->rowid. ', entity=' .$conf->entity."\n";
+ $this->errors[] = 'Failed to load invoice template with id=' .$line->rowid. ', entity=' .$conf->entity;
+ dol_syslog('createRecurringInvoices Failed to load invoice template with id=' .$line->rowid. ', entity=' .$conf->entity);
+ }
+
+ if (!$error && $invoiceidgenerated >= 0) {
+ $facturerec->nb_gen_done++;
+ $facturerec->date_last_gen = dol_now();
+ $facturerec->date_when= $facturerec->getNextDate();
+ $facturerec->update($user);
+ $this->db->commit('createRecurringInvoices Process invoice template id=' .$facturerec->id. ', title=' .$facturerec->titre);
+ dol_syslog('createRecurringInvoices Process invoice template ' .$facturerec->titre. ' is finished with a success generation');
+ $nb_create++;
+ $this->output .= $langs->trans('InvoiceGeneratedFromTemplate', $new_fac_fourn->ref, $facturerec->titre)."\n";
+ } else {
+ $this->db->rollback('createRecurringInvoices Process invoice template id=' .$facturerec->id. ', title=' .$facturerec->titre);
+ }
+
+ $parameters = array(
+ 'cpt' => $i,
+ 'total' => $num,
+ 'errorCount' => $error,
+ 'invoiceidgenerated' => $invoiceidgenerated,
+ 'facturerec' => $facturerec, // it's an object which PHP passes by "reference", so modifiable by hooks.
+ 'this' => $this, // it's an object which PHP passes by "reference", so modifiable by hooks.
+ );
+ $reshook = $hookmanager->executeHooks('afterCreationOfRecurringInvoice', $parameters, $new_fac_fourn); // note: $facture can be modified by hooks (warning: $facture can be null)
+
+ $i++;
+ }
+
+ $conf->entity = $saventity; // Restore entity context
+ } else {
+ dol_print_error($this->db);
+ }
+
+ $this->output = trim($this->output);
+
+ return $error ? $error : 0;
+ }
+
+ /**
+ * Return clicable name (with picto eventually)
+ *
+ * @param int $withpicto Add picto into link
+ * @param string $option Where point the link
+ * @param int $max Maxlength of ref
+ * @param int $short 1=Return just URL
+ * @param string $moretitle Add more text to title tooltip
+ * @param int $notooltip 1=Disable tooltip
+ * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
+ * @return string String with URL
+ */
+ public function getNomUrl($withpicto = 0, $option = '', $max = 0, $short = 0, $moretitle = '', $notooltip = '', $save_lastsearch_value = -1)
+ {
+ global $langs, $hookmanager;
+
+ $result = '';
+
+ $label = ''.$langs->trans('RepeatableInvoice').' ';
+ if (!empty($this->ref)) {
+ $label .= ''.$langs->trans('Ref').': '.$this->ref;
+ }
+ if ($this->frequency > 0) {
+ $label .= ''.$langs->trans('Frequency').': '.$langs->trans('FrequencyPer_'.$this->unit_frequency, $this->frequency);
+ }
+ if (!empty($this->date_last_gen)) {
+ $label .= ''.$langs->trans('DateLastGeneration').': '.dol_print_date($this->date_last_gen, 'dayhour');
+ }
+ if ($this->frequency > 0) {
+ if (!empty($this->date_when)) {
+ $label .= ''.$langs->trans('NextDateToExecution').': ';
+ $label .= (empty($this->suspended) ? '' : '').dol_print_date($this->date_when, 'day').(empty($this->suspended) ? '' : ' '); // No hour for this property
+ if (!empty($this->suspended)) {
+ $label .= ' ('.$langs->trans('Disabled').')';
+ }
+ }
+ }
+
+ $url = DOL_URL_ROOT.'/fourn/facture/card-rec.php?facid='.$this->id;
+
+ if ($short) {
+ return $url;
+ }
+
+ if ($option != 'nolink') {
+ // Add param to save lastsearch_values or not
+ $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
+ if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER['PHP_SELF'])) {
+ $add_save_lastsearch_values = 1;
+ }
+ if ($add_save_lastsearch_values) {
+ $url .= '&save_lastsearch_values=1';
+ }
+ }
+
+ $linkstart = '';
+ $linkend = ' ';
+
+ $result .= $linkstart;
+ if ($withpicto) {
+ $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
+ }
+ if ($withpicto != 2) {
+ $result .= $this->ref;
+ }
+ $result .= $linkend;
+ global $action;
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) {
+ $result = $hookmanager->resPrint;
+ } else {
+ $result .= $hookmanager->resPrint;
+ }
+ return $result;
+ }
+
+ /**
+ * Return label of object status
+ *
+ * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=short label + picto, 6=Long label + picto
+ * @param integer $alreadypaid Not used on recurring invoices
+ * @return string Label of status
+ */
+ public function getLibStatut($mode = 0, $alreadypaid = -1)
+ {
+ return $this->LibStatut($this->frequency ? 1 : 0, $this->suspended, $mode, $alreadypaid, empty($this->type) ? 0 : $this->type);
+ }
+
+ // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+ /**
+ * Return label of a status
+ *
+ * @param int $recur Is it a recurring invoice ?
+ * @param int $status Id status (suspended or not)
+ * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=short label + picto, 6=long label + picto
+ * @param integer $alreadypaid Not used for recurring invoices
+ * @param int $type Type invoice
+ * @return string Label of status
+ */
+ public function LibStatut($recur, $status, $mode = 0, $alreadypaid = -1, $type = 0)
+ {
+ // phpcs:enable
+ global $langs;
+ $langs->load('bills');
+
+ $labelStatus = $langs->transnoentitiesnoconv('Active');
+ $statusType = 'status0';
+
+ //print "$recur,$status,$mode,$alreadypaid,$type";
+ if ($mode == 0) {
+ if ($recur) {
+ if ($status == self::STATUS_SUSPENDED) {
+ $labelStatus = $langs->transnoentitiesnoconv('Disabled');
+ } else {
+ $labelStatus = $langs->transnoentitiesnoconv('Active');
+ }
+ } else {
+ if ($status == self::STATUS_SUSPENDED) {
+ $labelStatus = $langs->transnoentitiesnoconv('Disabled');
+ } else {
+ $labelStatus = $langs->transnoentitiesnoconv('Draft');
+ }
+ }
+ } elseif ($mode == 1) {
+ $prefix = 'Short';
+ if ($recur) {
+ if ($status == self::STATUS_SUSPENDED) {
+ $labelStatus = $langs->transnoentitiesnoconv('Disabled');
+ } else {
+ $labelStatus = $langs->transnoentitiesnoconv('Active');
+ }
+ } else {
+ if ($status == self::STATUS_SUSPENDED) {
+ $labelStatus = $langs->transnoentitiesnoconv('Disabled');
+ } else {
+ $labelStatus = $langs->transnoentitiesnoconv('Draft');
+ }
+ }
+ } elseif ($mode == 2) {
+ if ($recur) {
+ if ($status == self::STATUS_SUSPENDED) {
+ $statusType = 'status6';
+ $labelStatus = $langs->transnoentitiesnoconv('Disabled');
+ } else {
+ $statusType = 'status4';
+ $labelStatus = $langs->transnoentitiesnoconv('Active');
+ }
+ } else {
+ if ($status == self::STATUS_SUSPENDED) {
+ $statusType = 'status6';
+ $labelStatus = $langs->transnoentitiesnoconv('Disabled');
+ } else {
+ $statusType = 'status0';
+ $labelStatus = $langs->transnoentitiesnoconv('Draft');
+ }
+ }
+ } elseif ($mode == 3) {
+ if ($recur) {
+ $prefix = 'Short';
+ if ($status == self::STATUS_SUSPENDED) {
+ $statusType = 'status6';
+ $labelStatus = $langs->transnoentitiesnoconv('Disabled');
+ } else {
+ $statusType = 'status4';
+ $labelStatus = $langs->transnoentitiesnoconv('Active');
+ }
+ } else {
+ if ($status == self::STATUS_SUSPENDED) {
+ $statusType = 'status6';
+ $labelStatus = $langs->transnoentitiesnoconv('Disabled');
+ } else {
+ $statusType = 'status0';
+ $labelStatus = $langs->transnoentitiesnoconv('Draft');
+ }
+ }
+ } elseif ($mode == 4) {
+ $prefix = '';
+ if ($recur) {
+ if ($status == self::STATUS_SUSPENDED) {
+ $statusType = 'status6';
+ $labelStatus = $langs->transnoentitiesnoconv('Disabled');
+ } else {
+ $statusType = 'status4';
+ $labelStatus = $langs->transnoentitiesnoconv('Active');
+ }
+ } else {
+ if ($status == self::STATUS_SUSPENDED) {
+ $statusType = 'status6';
+ $labelStatus = $langs->transnoentitiesnoconv('Disabled');
+ } else {
+ $statusType = 'status0';
+ $labelStatus = $langs->transnoentitiesnoconv('Draft');
+ }
+ }
+ } elseif ($mode == 5 || $mode == 6) {
+ $prefix = '';
+ if ($mode == 5) {
+ $prefix = 'Short';
+ }
+ if ($recur) {
+ if ($status == self::STATUS_SUSPENDED) {
+ $statusType = 'status6';
+ $labelStatus = $langs->transnoentitiesnoconv('Disabled');
+ } else {
+ $statusType = 'status4';
+ $labelStatus = $langs->transnoentitiesnoconv('Active');
+ }
+ } else {
+ if ($status == self::STATUS_SUSPENDED) {
+ $statusType = 'status6';
+ $labelStatus = $langs->transnoentitiesnoconv('Disabled');
+ } else {
+ $statusType = 'status0';
+ $labelStatus = $langs->transnoentitiesnoconv('Draft');
+ }
+ }
+ }
+
+ $labelStatusShort = $labelStatus;
+
+ return dolGetStatus($labelStatus, $labelStatusShort, '', $statusType, $mode);
+ }
+
+ /**
+ * Initialise an instance with random values.
+ * Used to build previews or test instances.
+ * id must be 0 if object instance is a specimen.
+ *
+ * @param string $option ''=Create a specimen invoice with lines, 'nolines'=No lines
+ * @return void
+ */
+ public function initAsSpecimen($option = '')
+ {
+ global $user, $langs, $conf;
+
+ $now = dol_now();
+ $arraynow = dol_getdate($now);
+ $nownotime = dol_mktime(0, 0, 0, $arraynow['mon'], $arraynow['mday'], $arraynow['year']);
+
+ // Load array of products prodids
+ $num_prods = 0;
+ $prodids = array();
+
+ $sql = 'SELECT rowid';
+ $sql .= ' FROM ' .MAIN_DB_PREFIX. 'product';
+ $sql .= ' WHERE entity IN (' .getEntity('product'). ')';
+ $sql .= $this->db->plimit(100);
+
+ $resql = $this->db->query($sql);
+ if ($resql) {
+ $num_prods = $this->db->num_rows($resql);
+ $i = 0;
+ while ($i < $num_prods) {
+ $i++;
+ $row = $this->db->fetch_row($resql);
+ $prodids[$i] = $row[0];
+ }
+ }
+
+ // Initialize parameters
+ $this->id = 0;
+ $this->ref = 'SPECIMEN';
+ $this->title = 'SPECIMEN';
+ $this->specimen = 1;
+ $this->socid = 1;
+ $this->date = $nownotime;
+ $this->date_lim_reglement = $nownotime + 3600 * 24 * 30;
+ $this->cond_reglement_id = 1;
+ $this->cond_reglement_code = 'RECEP';
+ $this->date_lim_reglement = $this->calculate_date_lim_reglement();
+ $this->mode_reglement_id = 0; // Not forced to show payment mode CHQ + VIR
+ $this->mode_reglement_code = ''; // Not forced to show payment mode CHQ + VIR
+ $this->note_public = 'This is a comment (public)';
+ $this->note_private = 'This is a comment (private)';
+ $this->note = 'This is a comment (private)';
+ $this->fk_incoterms = 0;
+ $this->location_incoterms = '';
+
+ if (empty($option) || $option != 'nolines') {
+ // Lines
+ $nbp = 5;
+ $xnbp = 0;
+ while ($xnbp < $nbp) {
+ $line = new FactureLigne($this->db);
+ $line->desc = $langs->trans('Description'). ' ' .$xnbp;
+ $line->qty = 1;
+ $line->subprice = 100;
+ $line->tva_tx = 19.6;
+ $line->localtax1_tx = 0;
+ $line->localtax2_tx = 0;
+ $line->remise_percent = 0;
+ if ($xnbp == 1) { // Qty is negative (product line)
+ $prodid = mt_rand(1, $num_prods);
+ $line->fk_product = $prodids[$prodid];
+ $line->qty = -1;
+ $line->total_ht = -100;
+ $line->total_ttc = -119.6;
+ $line->total_tva = -19.6;
+ } elseif ($xnbp == 2) { // UP is negative (free line)
+ $line->subprice = -100;
+ $line->total_ht = -100;
+ $line->total_ttc = -119.6;
+ $line->total_tva = -19.6;
+ $line->remise_percent = 0;
+ } elseif ($xnbp == 3) { // Discount is 50% (product line)
+ $prodid = mt_rand(1, $num_prods);
+ $line->fk_product = $prodids[$prodid];
+ $line->total_ht = 50;
+ $line->total_ttc = 59.8;
+ $line->total_tva = 9.8;
+ $line->remise_percent = 50;
+ } else // (product line)
+ {
+ $prodid = mt_rand(1, $num_prods);
+ $line->fk_product = $prodids[$prodid];
+ $line->total_ht = 100;
+ $line->total_ttc = 119.6;
+ $line->total_tva = 19.6;
+ $line->remise_percent = 00;
+ }
+
+ $this->lines[$xnbp] = $line;
+ $xnbp++;
+
+ $this->total_ht += $line->total_ht;
+ $this->total_tva += $line->total_tva;
+ $this->total_ttc += $line->total_ttc;
+ }
+ $this->revenuestamp = 0;
+
+ // Add a line "offered"
+ $line = new FactureLigne($this->db);
+ $line->desc = $langs->trans('Description'). ' (offered line)';
+ $line->qty = 1;
+ $line->subprice = 100;
+ $line->tva_tx = 19.6;
+ $line->localtax1_tx = 0;
+ $line->localtax2_tx = 0;
+ $line->remise_percent = 100;
+ $line->total_ht = 0;
+ $line->total_ttc = 0; // 90 * 1.196
+ $line->total_tva = 0;
+ $prodid = mt_rand(1, $num_prods);
+ $line->fk_product = $prodids[$prodid];
+
+ $this->lines[$xnbp] = $line;
+ $xnbp++;
+ }
+
+ $this->usenewprice = 0;
+ }
+
+ /**
+ * Function used to replace a thirdparty id with another one.
+ *
+ * @param DoliDB $db Database handler
+ * @param int $origin_id Old thirdparty id
+ * @param int $dest_id New thirdparty id
+ * @return bool
+ */
+ public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
+ {
+ $tables = array(
+ 'facture_rec'
+ );
+
+ return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
+ }
+
+ /**
+ * Update frequency and unit
+ *
+ * @param int $frequency value of frequency
+ * @param string $unit unit of frequency (d, m, y)
+ * @return int <0 if KO, >0 if OK
+ */
+ public function setFrequencyAndUnit($frequency, $unit)
+ {
+ if (!$this->table_element) {
+ dol_syslog(get_class($this). '::setFrequencyAndUnit was called on objet with property table_element not defined', LOG_ERR);
+ return -1;
+ }
+
+ if (!empty($frequency) && empty($unit)) {
+ dol_syslog(get_class($this). '::setFrequencyAndUnit was called on objet with params frequency defined but unit not defined', LOG_ERR);
+ return -2;
+ }
+
+ $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
+ $sql .= ' SET frequency = '.($frequency ? $this->db->escape($frequency) : 'null');
+ if (!empty($unit)) {
+ $sql .= ', unit_frequency = '.$this->db->escape($unit);
+ }
+ $sql .= ' WHERE rowid = ' . (int) $this->id;
+
+ dol_syslog(get_class($this). '::setFrequencyAndUnit', LOG_DEBUG);
+ if ($this->db->query($sql)) {
+ $this->frequency = $frequency;
+ if (!empty($unit)) {
+ $this->unit_frequency = $unit;
+ }
+ return 1;
+ } else {
+ dol_print_error($this->db);
+ return -1;
+ }
+ }
+
+ /**
+ * Update the next date of execution
+ *
+ * @param datetime $date date of execution
+ * @param int $increment_nb_gen_done 0 do nothing more, >0 increment nb_gen_done
+ * @return int <0 if KO, >0 if OK
+ */
+ public function setNextDate($date, $increment_nb_gen_done = 0)
+ {
+ if (!$this->table_element) {
+ dol_syslog(get_class($this). '::setNextDate was called on objet with property table_element not defined', LOG_ERR);
+ return -1;
+ }
+ $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
+ $sql .= ' SET date_when = ' .($date ? "'".$this->db->idate($date)."'" : 'null');
+ if ($increment_nb_gen_done > 0) {
+ $sql .= ', nb_gen_done = nb_gen_done + 1';
+ }
+ $sql .= ' WHERE rowid = ' . (int) $this->id;
+
+ dol_syslog(get_class($this). '::setNextDate', LOG_DEBUG);
+ if ($this->db->query($sql)) {
+ $this->date_when = $date;
+ if ($increment_nb_gen_done > 0) {
+ $this->nb_gen_done++;
+ }
+ return 1;
+ } else {
+ dol_print_error($this->db);
+ return -1;
+ }
+ }
+
+ /**
+ * Update the maximum period
+ *
+ * @param int $nb number of maximum period
+ * @return int <0 if KO, >0 if OK
+ */
+ public function setMaxPeriod($nb)
+ {
+ if (!$this->table_element) {
+ dol_syslog(get_class($this). '::setMaxPeriod was called on objet with property table_element not defined', LOG_ERR);
+ return -1;
+ }
+
+ if (empty($nb)) {
+ $nb = 0;
+ }
+
+ $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
+ $sql .= ' SET nb_gen_max = '. (int) $nb;
+ $sql .= ' WHERE rowid = ' . (int) $this->id;
+
+ dol_syslog(get_class($this). '::setMaxPeriod', LOG_DEBUG);
+ if ($this->db->query($sql)) {
+ $this->nb_gen_max = $nb;
+ return 1;
+ } else {
+ dol_print_error($this->db);
+ return -1;
+ }
+ }
+
+ /**
+ * Update the auto validate flag of invoice
+ *
+ * @param int $validate 0 to create in draft, 1 to create and validate invoice
+ * @return int <0 if KO, >0 if OK
+ */
+ public function setAutoValidate($validate)
+ {
+ if (!$this->table_element) {
+ dol_syslog(get_class($this). '::setAutoValidate was called on objet with property table_element not defined', LOG_ERR);
+ return -1;
+ }
+
+ $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
+ $sql .= ' SET auto_validate = '.((int) $validate);
+ $sql .= ' WHERE rowid = ' . (int) $this->id;
+
+ dol_syslog(get_class($this). '::setAutoValidate', LOG_DEBUG);
+ if ($this->db->query($sql)) {
+ $this->auto_validate = $validate;
+ return 1;
+ } else {
+ dol_print_error($this->db);
+ return -1;
+ }
+ }
+
+ /**
+ * Update the auto generate documents
+ *
+ * @param int $validate 0 no document, 1 to generate document
+ * @return int <0 if KO, >0 if OK
+ */
+ public function setGeneratePdf($validate)
+ {
+ if (!$this->table_element) {
+ dol_syslog(get_class($this). '::setGeneratePdf was called on objet with property table_element not defined', LOG_ERR);
+ return -1;
+ }
+
+ $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
+ $sql .= ' SET generate_pdf = '. (int) $validate;
+ $sql .= ' WHERE rowid = ' . (int) $this->id;
+
+ dol_syslog(get_class($this). '::setGeneratePdf', LOG_DEBUG);
+ if ($this->db->query($sql)) {
+ $this->generate_pdf = $validate;
+ return 1;
+ } else {
+ dol_print_error($this->db);
+ return -1;
+ }
+ }
+
+ /**
+ * Update the model for documents
+ *
+ * @param string $model model of document generator
+ * @return int <0 if KO, >0 if OK
+ */
+ public function setModelPdf($model)
+ {
+ if (!$this->table_element) {
+ dol_syslog(get_class($this). '::setModelPdf was called on objet with property table_element not defined', LOG_ERR);
+ return -1;
+ }
+
+ $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
+ $sql .= " SET modelpdf = '".$this->db->escape($model)."'";
+ $sql .= ' WHERE rowid = ' . (int) $this->id;
+
+ dol_syslog(get_class($this). '::setModelPdf', LOG_DEBUG);
+ if ($this->db->query($sql)) {
+ $this->model_pdf = $model;
+ return 1;
+ } else {
+ dol_print_error($this->db);
+ return -1;
+ }
+ }
+}
+
+
+
+/**
+ * Class to manage supplier invoice lines of templates.
+ * Saved into database table llx_facture_fourn_det_rec
+ */
+class FactureFournisseurLigneRec extends CommonObjectLine
+{
+ /**
+ * @var string ID to identify managed object
+ */
+ public $element = 'invoice_supplier_det_rec';
+
+ /**
+ * @var string Name of table without prefix where object is stored
+ */
+ public $table_element = 'facture_fourn_det_rec';
+
+ public $fk_facture_fourn;
+ public $fk_parent;
+ public $fk_product;
+ public $ref_supplier;
+ public $label;
+ public $description;
+ public $pu_ht;
+ public $pu_ttc;
+ public $qty;
+ public $remise_percent;
+ public $fk_remise_except;
+ public $vat_src_code;
+ public $tva_tx;
+ public $localtax1_tx;
+ public $localtax1_type;
+ public $localtax2_tx;
+ public $localtax2_type;
+
+ public $product_type;
+ public $date_start;
+ public $date_end;
+ public $info_bits;
+ public $special_code;
+ public $rang;
+
+ public $fk_user_author;
+ public $fk_user_modif;
+ public $fk_multicurrency;
+ public $multicurrency_subprice;
+
+
+ /* Overrides fields in CommonObject
+ public $total_ht;
+ public $total_tva;
+ public $total_localtax1;
+ public $total_localtax2;
+ public $total_ttc;
+
+ public $fk_unit;
+ public $import_key;
+ public $multicurrency_code;
+ public $multicurrency_total_ht;
+ public $multicurrency_total_tva;
+ public $multicurrency_total_ttc;
+ */
+
+
+ /**
+ * Delete supplier order template line in database
+ *
+ * @param User $user Object user
+ * @param int $notrigger Disable triggers
+ * @return int <0 if KO, >0 if OK
+ */
+ public function delete(User $user, $notrigger = false)
+ {
+ $error = 0;
+ $this->db->begin();
+
+ if (! $error) {
+ if (! $notrigger) {
+ // Call triggers
+ $result = $this->call_trigger('LINEBILLREC_DELETE', $user);
+ if ($result < 0) {
+ $error++;
+ } // Do also here what you must do to rollback action if trigger fail
+ // End call triggers
+ }
+ }
+
+ if (! $error) {
+ $result = $this->deleteExtraFields();
+ if ($result < 0) {
+ $error++;
+ }
+ }
+
+ if (! $error) {
+ $sql = 'DELETE FROM ' . MAIN_DB_PREFIX . $this->table_element . ' WHERE rowid=' . (int) $this->id;
+
+ $res = $this->db->query($sql);
+ if ($res === false) {
+ $error++;
+ $this->errors[] = $this->db->lasterror();
+ }
+ }
+
+ // Commit or rollback
+ if ($error) {
+ $this->db->rollback();
+ return -1;
+ } else {
+ $this->db->commit();
+ return 1;
+ }
+ }
+
+
+ /**
+ * Get line of template invoice
+ *
+ * @param int $rowid Id of invoice
+ * @return int 1 if OK, < 0 if KO
+ */
+ public function fetch($rowid)
+ {
+ $sql = 'SELECT l.rowid,';
+ $sql .= ' l.fk_facture_fourn, l.fk_parent_line, l.fk_product,';
+ $sql .= ' l.ref as ref_supplier, l.label, l.description, l.pu_ht, l.pu_ttc, l.qty, l.remise_percent, l.fk_remise_except,';
+ $sql .= ' l.vat_src_code, l.tva_tx, l.localtax1_tx, l.localtax1_type, l.localtax2_tx, l.localtax2_type,';
+ $sql .= ' l.total_ht, l.total_tva, l.total_localtax1, l.total_localtax2, l.total_ttc,';
+ $sql .= ' l.product_type, l.date_start, l.date_end,';
+ $sql .= ' l.info_bits, l.special_code, l.rang, l.fk_unit, l.import_key,';
+ $sql .= ' l.fk_user_author, l.fk_user_modif, l.fk_multicurrency,';
+ $sql .= ' l.multicurrency_code, l.multicurrency_subprice, l.multicurrency_total_ht, l.multicurrency_total_tva, l.multicurrency_total_ttc,';
+ $sql .= ' p.ref as product_ref, p.fk_product_type as fk_product_type, p.label as product_label, p.description as product_desc';
+ $sql .= ' FROM '.MAIN_DB_PREFIX.'facture_fourn_det_rec as l';
+ $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON l.fk_product = p.rowid';
+ $sql .= ' WHERE l.rowid = '. (int) $rowid;
+ $sql .= ' ORDER BY l.rang';
+
+ dol_syslog('FactureRec::fetch', LOG_DEBUG);
+ $result = $this->db->query($sql);
+ if ($result) {
+ $objp = $this->db->fetch_object($result);
+
+ $this->id = $objp->rowid;
+ $this->fk_facture_fourn = $objp->fk_facture_fourn;
+ $this->fk_parent = $objp->fk_parent_line;
+ $this->fk_product = $objp->fk_product;
+ $this->ref_supplier = $objp->ref_supplier;
+ $this->label = $objp->label;
+ $this->description = $objp->description;
+ $this->pu_ht = $objp->pu_ht;
+ $this->pu_ttc = $objp->pu_ttc;
+ $this->qty = $objp->qty;
+ $this->remise_percent = $objp->remise_percent;
+ $this->fk_remise_except = $objp->fk_remise_except;
+ $this->vat_src_code = $objp->vat_src_code;
+ $this->tva_tx = $objp->tva_tx;
+ $this->localtax1_tx = $objp->localtax1_tx;
+ $this->localtax1_type = $objp->localtax1_type;
+ $this->localtax2_tx = $objp->localtax2_tx;
+ $this->localtax2_type = $objp->localtax2_type;
+ $this->total_ht = $objp->total_ht;
+ $this->total_tva = $objp->total_tva;
+ $this->total_localtax1 = $objp->total_localtax1;
+ $this->total_localtax2 = $objp->total_localtax2;
+ $this->total_ttc = $objp->total_ttc;
+ $this->product_type = $objp->product_type;
+ $this->date_start = $objp->date_start;
+ $this->date_end = $objp->date_end;
+ $this->info_bits = $objp->info_bits ;
+ $this->special_code = $objp->special_code;
+ $this->rang = $objp->rang;
+ $this->fk_unit = $objp->fk_unit;
+ $this->import_key = $objp->import_key;
+ $this->fk_user_author = $objp->fk_user_author;
+ $this->fk_user_modif = $objp->fk_user_modif;
+ $this->fk_multicurrency = $objp->fk_multicurrency;
+ $this->multicurrency_code = $objp->multicurrency_code;
+ $this->multicurrency_subprice = $objp->multicurrency_subprice;
+ $this->multicurrency_total_ht = $objp->multicurrency_total_ht;
+ $this->multicurrency_total_tva = $objp->multicurrency_total_tva;
+ $this->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
+
+ $this->db->free($result);
+ return 1;
+ } else {
+ $this->error = $this->db->lasterror();
+ return -3;
+ }
+ }
+
+
+ /**
+ * Update a line to supplier invoice template .
+ *
+ * @param User $user User
+ * @param int $notrigger No trigger
+ * @return int <0 if KO, Id of line if OK
+ */
+ public function update(User $user, $notrigger = 0)
+ {
+ global $conf;
+
+ $error = 0;
+
+ include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
+
+ $sql = 'UPDATE ' . MAIN_DB_PREFIX . 'facture_fourn_det_rec SET';
+ $sql .= ' fk_facture_fourn = ' . (int) $this->fk_facture_fourn;
+ $sql .= ', fk_parent_line = ' . (int) $this->fk_parent;
+ $sql .= ', fk_product = ' . (int) $this->fk_product;
+ $sql .= ', ref = ' . (! empty($this->ref) ? "'" . $this->db->escape($this->ref) . "'" : 'null');
+ $sql .= ", label = " . (! empty($this->label) ? "'" . $this->db->escape($this->label) . "'" : 'null');
+ $sql .= ", description = '" . $this->db->escape($this->description) . "'";
+ $sql .= ', pu_ht = ' . price2num($this->pu_ht);
+ $sql .= ', pu_ttc = ' . price2num($this->pu_ttc);
+ $sql .= ', qty = ' . price2num($this->qty);
+ $sql .= ", remise_percent = '" . price2num($this->remise_percent) . "'";
+ $sql .= ', fk_remise_except = ' . (int) $this->fk_remise_except;
+ $sql .= ", vat_src_code = '" . $this->db->escape($this->vat_src_code) . "'";
+ $sql .= ', tva_tx =' . price2num($this->tva_tx);
+ $sql .= ', localtax1_tx = ' . price2num($this->localtax1_tx);
+ $sql .= ", localtax1_type = '" . $this->db->escape($this->localtax1_type) . "'";
+ $sql .= ', localtax2_tx = ' . price2num($this->localtax2_tx);
+ $sql .= ", localtax2_type = '" . $this->db->escape($this->localtax2_type) . "'";
+ if (empty($this->skip_update_total)) {
+ $sql .= ', total_ht =' . price2num($this->total_ht);
+ $sql .= ', total_tva =' . price2num($this->total_tva);
+ $sql .= ', total_localtax1 =' . price2num($this->total_localtax1);
+ $sql .= ', total_localtax2 =' . price2num($this->total_localtax2);
+ $sql .= ', total_ttc =' . price2num($this->total_ttc);
+ }
+ $sql .= ', product_type =' . (int) $this->product_type;
+ $sql .= ', date_start =' . (int) $this->date_start;
+ $sql .= ', date_end =' . (int) $this->date_end;
+ $sql .= ", info_bits ='" . price2num($this->info_bits) . "'";
+ $sql .= ', special_code =' . (int) $this->special_code;
+ $sql .= ', rang =' . (int) $this->rang;
+ $sql .= ', fk_unit =' .($this->fk_unit ? "'".$this->db->escape($this->fk_unit)."'" : 'null');
+ $sql .= ', fk_user_modif =' . (int) $user;
+
+ $sql .= ' WHERE rowid = ' . (int) $this->id;
+
+ $this->db->begin();
+
+ dol_syslog(get_class($this). '::updateline', LOG_DEBUG);
+ $resql = $this->db->query($sql);
+ if ($resql) {
+ if (!$error) {
+ $result = $this->insertExtraFields();
+ if ($result < 0) {
+ $error++;
+ }
+ }
+
+ if (!$error && !$notrigger) {
+ // Call trigger
+ $result = $this->call_trigger('LINESUPPLIERBILLREC_UPDATE', $user);
+ if ($result < 0) {
+ $error++;
+ }
+ // End call triggers
+ }
+
+ if ($error) {
+ $this->db->rollback();
+ return -2;
+ } else {
+ $this->db->commit();
+ return 1;
+ }
+ } else {
+ $this->error = $this->db->lasterror();
+ $this->db->rollback();
+ return -2;
+ }
+ }
+}
diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php
index e9db81e298f..922d9f25e29 100644
--- a/htdocs/fourn/class/fournisseur.facture.class.php
+++ b/htdocs/fourn/class/fournisseur.facture.class.php
@@ -251,6 +251,8 @@ class FactureFournisseur extends CommonInvoice
*/
public $fk_facture_source;
+ public $fac_rec;
+
public $fields = array(
'rowid' =>array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>10),
@@ -410,6 +412,128 @@ class FactureFournisseur extends CommonInvoice
$this->db->begin();
+ // Create invoice from a template recurring invoice
+ if ($this->fac_rec > 0) {
+ $this->fk_fac_rec_source = $this->fac_rec;
+
+ require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.facture-rec.class.php';
+ $_facrec = new FactureFournisseurRec($this->db);
+ $result = $_facrec->fetch($this->fac_rec);
+ $result = $_facrec->fetchObjectLinked(null, '', null, '', 'OR', 1, 'sourcetype', 0); // This load $_facrec->linkedObjectsIds
+
+ // Define some dates
+ if (! empty($_facrec->frequency)) {
+ $originaldatewhen = $_facrec->date_when;
+ $nextdatewhen = dol_time_plus_duree($originaldatewhen, $_facrec->frequency, $_facrec->unit_frequency);
+ $previousdaynextdatewhen = dol_time_plus_duree($nextdatewhen, -1, 'd');
+ $this->socid = $_facrec->socid;
+ }
+
+ $this->entity = $_facrec->entity; // Invoice created in same entity than template
+
+ // Fields coming from GUI (priority on template). TODO Value of template should be used as default value on GUI so we can use here always value from GUI
+ $this->fk_projet = GETPOST('projectid', 'int') > 0 ? ((int) GETPOST('projectid', 'int')) : $_facrec->fk_projet;
+ $this->note_public = GETPOST('note_public', 'restricthtml') ? GETPOST('note_public', 'restricthtml') : $_facrec->note_public;
+ $this->note_private = GETPOST('note_private', 'restricthtml') ? GETPOST('note_private', 'restricthtml') : $_facrec->note_private;
+ $this->model_pdf = GETPOST('model', 'alpha') ? GETPOST('model', 'alpha') : $_facrec->model_pdf;
+ $this->cond_reglement_id = GETPOST('cond_reglement_id', 'int') > 0 ? ((int) GETPOST('cond_reglement_id', 'int')) : $_facrec->cond_reglement_id;
+ $this->mode_reglement_id = GETPOST('mode_reglement_id', 'int') > 0 ? ((int) GETPOST('mode_reglement_id', 'int')) : $_facrec->mode_reglement_id;
+ $this->fk_account = GETPOST('fk_account') > 0 ? ((int) GETPOST('fk_account')) : $_facrec->fk_account;
+
+ // Set here to have this defined for substitution into notes, should be recalculated after adding lines to get same result
+ $this->total_ht = $_facrec->total_ht;
+ $this->total_ttc = $_facrec->total_ttc;
+
+ // Fields always coming from template
+ $this->remise = $_facrec->remise;
+ $this->fk_incoterms = $_facrec->fk_incoterms;
+ $this->location_incoterms = $_facrec->location_incoterms;
+
+ // Clean parameters
+ if (! $this->type) {
+ $this->type = self::TYPE_STANDARD;
+ }
+ if (! empty(GETPOST('ref_supplier'))) {
+ $this->ref_supplier = trim($this->ref_supplier);
+ } else {
+ $this->ref_supplier = trim($this->ref_supplier . '_' . ($_facrec->nb_gen_done + 1));
+ }
+ $this->note_public = trim($this->note_public);
+ $this->note_private = trim($this->note_private);
+ $this->note_private = dol_concatdesc($this->note_private, $langs->trans("GeneratedFromRecurringInvoice", $_facrec->titre));
+
+ $this->array_options = $_facrec->array_options;
+
+ //if (! $this->remise) $this->remise = 0;
+ if (! $this->mode_reglement_id) {
+ $this->mode_reglement_id = 0;
+ }
+ $this->brouillon = 1;
+ $this->status = self::STATUS_DRAFT;
+ $this->statut = self::STATUS_DRAFT;
+
+ $this->linked_objects = $_facrec->linkedObjectsIds;
+ // We do not add link to template invoice or next invoice will be linked to all generated invoices
+ //$this->linked_objects['facturerec'][0] = $this->fac_rec;
+
+ $forceduedate = $this->calculate_date_lim_reglement();
+
+ // For recurring invoices, update date and number of last generation of recurring template invoice, before inserting new invoice
+ if ($_facrec->frequency > 0) {
+ dol_syslog("This is a recurring invoice so we set date_last_gen and next date_when");
+ if (empty($_facrec->date_when)) {
+ $_facrec->date_when = $now;
+ }
+ $next_date = $_facrec->getNextDate(); // Calculate next date
+ $result = $_facrec->setValueFrom('date_last_gen', $now, '', null, 'date', '', $user, '');
+ //$_facrec->setValueFrom('nb_gen_done', $_facrec->nb_gen_done + 1); // Not required, +1 already included into setNextDate when second param is 1.
+ $result = $_facrec->setNextDate($next_date, 1);
+ }
+
+ // Define lang of customer
+ $outputlangs = $langs;
+ $newlang = '';
+
+ if ($conf->global->MAIN_MULTILANGS && empty($newlang) && isset($this->thirdparty->default_lang)) {
+ $newlang = $this->thirdparty->default_lang; // for proposal, order, invoice, ...
+ }
+ if ($conf->global->MAIN_MULTILANGS && empty($newlang) && isset($this->default_lang)) {
+ $newlang = $this->default_lang; // for thirdparty
+ }
+ if (! empty($newlang)) {
+ $outputlangs = new Translate("", $conf);
+ $outputlangs->setDefaultLang($newlang);
+ }
+
+ // Array of possible substitutions (See also file mailing-send.php that should manage same substitutions)
+ $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $this);
+ $substitutionarray['__INVOICE_PREVIOUS_MONTH__'] = dol_print_date(dol_time_plus_duree($this->date, -1, 'm'), '%m');
+ $substitutionarray['__INVOICE_MONTH__'] = dol_print_date($this->date, '%m');
+ $substitutionarray['__INVOICE_NEXT_MONTH__'] = dol_print_date(dol_time_plus_duree($this->date, 1, 'm'), '%m');
+ $substitutionarray['__INVOICE_PREVIOUS_MONTH_TEXT__'] = dol_print_date(dol_time_plus_duree($this->date, -1, 'm'), '%B');
+ $substitutionarray['__INVOICE_MONTH_TEXT__'] = dol_print_date($this->date, '%B');
+ $substitutionarray['__INVOICE_NEXT_MONTH_TEXT__'] = dol_print_date(dol_time_plus_duree($this->date, 1, 'm'), '%B');
+ $substitutionarray['__INVOICE_PREVIOUS_YEAR__'] = dol_print_date(dol_time_plus_duree($this->date, -1, 'y'), '%Y');
+ $substitutionarray['__INVOICE_YEAR__'] = dol_print_date($this->date, '%Y');
+ $substitutionarray['__INVOICE_NEXT_YEAR__'] = dol_print_date(dol_time_plus_duree($this->date, 1, 'y'), '%Y');
+ // Only for template invoice
+ $substitutionarray['__INVOICE_DATE_NEXT_INVOICE_BEFORE_GEN__'] = dol_print_date($originaldatewhen, 'dayhour');
+ $substitutionarray['__INVOICE_DATE_NEXT_INVOICE_AFTER_GEN__'] = dol_print_date($nextdatewhen, 'dayhour');
+ $substitutionarray['__INVOICE_PREVIOUS_DATE_NEXT_INVOICE_AFTER_GEN__'] = dol_print_date($previousdaynextdatewhen, 'dayhour');
+ $substitutionarray['__INVOICE_COUNTER_CURRENT__'] = $_facrec->nb_gen_done;
+ $substitutionarray['__INVOICE_COUNTER_MAX__'] = $_facrec->nb_gen_max;
+
+ complete_substitutions_array($substitutionarray, $outputlangs);
+
+ $this->note_public = make_substitutions($this->note_public, $substitutionarray);
+ $this->note_private = make_substitutions($this->note_private, $substitutionarray);
+ }
+
+ // Define due date if not already defined
+ if (! empty($forceduedate)) {
+ $this->date_echeance = $forceduedate;
+ }
+
if (!$remise) {
$remise = 0;
}
@@ -437,6 +561,7 @@ class FactureFournisseur extends CommonInvoice
$sql .= ", multicurrency_code";
$sql .= ", multicurrency_tx";
$sql .= ", fk_facture_source";
+ $sql .= ", fk_fac_rec_source";
$sql .= ")";
$sql .= " VALUES (";
$sql .= "'(PROV)'";
@@ -462,6 +587,7 @@ class FactureFournisseur extends CommonInvoice
$sql .= ", '".$this->db->escape($this->multicurrency_code)."'";
$sql .= ", ".(double) $this->multicurrency_tx;
$sql .= ", ".(isset($this->fk_facture_source) ? $this->fk_facture_source : "NULL");
+ $sql .= ", ".(isset($this->fk_fac_rec_source) ? $this->fk_fac_rec_source : "NULL");
$sql .= ")";
dol_syslog(get_class($this)."::create", LOG_DEBUG);
@@ -506,7 +632,7 @@ class FactureFournisseur extends CommonInvoice
}
}
- if (count($this->lines) && is_object($this->lines[0])) { // If this->lines is array of InvoiceLines (preferred mode)
+ if (!$error && empty($this->fac_rec) && count($this->lines) && is_object($this->lines[0])) { // If this->lines is array of InvoiceLines (preferred mode)
dol_syslog("There is ".count($this->lines)." lines that are invoice lines objects");
foreach ($this->lines as $i => $val) {
$sql = 'INSERT INTO '.MAIN_DB_PREFIX.'facture_fourn_det (fk_facture_fourn, special_code, fk_remise_except)';
@@ -516,7 +642,7 @@ class FactureFournisseur extends CommonInvoice
if ($resql_insert) {
$idligne = $this->db->last_insert_id(MAIN_DB_PREFIX.'facture_fourn_det');
- $this->updateline(
+ $res = $this->updateline(
$idligne,
$this->lines[$i]->description,
$this->lines[$i]->pu_ht,
@@ -543,8 +669,7 @@ class FactureFournisseur extends CommonInvoice
return -5;
}
}
- } else // If this->lines is an array of invoice line arrays
- {
+ } elseif (!$error && empty($this->fac_rec)) { // If this->lines is an array of invoice line arrays
dol_syslog("There is ".count($this->lines)." lines that are array lines");
foreach ($this->lines as $i => $val) {
$line = $this->lines[$i];
@@ -591,6 +716,92 @@ class FactureFournisseur extends CommonInvoice
}
}
+ /*
+ * Insert lines of template invoices
+ */
+ if (! $error && $this->fac_rec > 0) {
+ foreach ($_facrec->lines as $i => $val) {
+ if ($_facrec->lines[$i]->fk_product) {
+ $prod = new Product($this->db);
+ $res = $prod->fetch($_facrec->lines[$i]->fk_product);
+ }
+
+ // For line from template invoice, we use data from template invoice
+ /*
+ $tva_tx = get_default_tva($mysoc,$soc,$prod->id);
+ $tva_npr = get_default_npr($mysoc,$soc,$prod->id);
+ if (empty($tva_tx)) $tva_npr=0;
+ $localtax1_tx=get_localtax($tva_tx,1,$soc,$mysoc,$tva_npr);
+ $localtax2_tx=get_localtax($tva_tx,2,$soc,$mysoc,$tva_npr);
+ */
+ $tva_tx = $_facrec->lines[$i]->tva_tx . ($_facrec->lines[$i]->vat_src_code ? '(' . $_facrec->lines[$i]->vat_src_code . ')' : '');
+ $tva_npr = $_facrec->lines[$i]->info_bits;
+ if (empty($tva_tx)) {
+ $tva_npr = 0;
+ }
+ $localtax1_tx = $_facrec->lines[$i]->localtax1_tx;
+ $localtax2_tx = $_facrec->lines[$i]->localtax2_tx;
+
+ $fk_product_fournisseur_price = empty($_facrec->lines[$i]->fk_product_fournisseur_price) ? null : $_facrec->lines[$i]->fk_product_fournisseur_price;
+ $buyprice = empty($_facrec->lines[$i]->buyprice) ? 0 : $_facrec->lines[$i]->buyprice;
+
+ // If buyprice not defined from template invoice, we try to guess the best value
+ if (! $buyprice && $_facrec->lines[$i]->fk_product > 0) {
+ require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.product.class.php';
+ $producttmp = new ProductFournisseur($this->db);
+ $producttmp->fetch($_facrec->lines[$i]->fk_product);
+
+ // If margin module defined on costprice, we try the costprice
+ // If not defined or if module margin defined and pmp and stock module enabled, we try pmp price
+ // else we get the best supplier price
+ if ($conf->global->MARGIN_TYPE == 'costprice' && ! empty($producttmp->cost_price)) {
+ $buyprice = $producttmp->cost_price;
+ } elseif (! empty($conf->stock->enabled) && ($conf->global->MARGIN_TYPE == 'costprice' || $conf->global->MARGIN_TYPE == 'pmp') && ! empty($producttmp->pmp)) {
+ $buyprice = $producttmp->pmp;
+ } else {
+ if ($producttmp->find_min_price_product_fournisseur($_facrec->lines[$i]->fk_product) > 0) {
+ if ($producttmp->product_fourn_price_id > 0) {
+ $buyprice = price2num($producttmp->fourn_unitprice * (1 - $producttmp->fourn_remise_percent / 100) + $producttmp->fourn_remise, 'MU');
+ }
+ }
+ }
+ }
+
+ $result_insert = $this->addline(
+ $_facrec->lines[$i]->description,
+ $_facrec->lines[$i]->pu_ht,
+ $tva_tx,
+ $localtax1_tx,
+ $localtax2_tx,
+ $_facrec->lines[$i]->qty,
+ $_facrec->lines[$i]->fk_product,
+ $_facrec->lines[$i]->remise_percent,
+ ($_facrec->lines[$i]->date_start == 1 && $this->date) ? $this->date : '',
+ ($_facrec->lines[$i]->date_end == 1 && $previousdaynextdatewhen) ? $previousdaynextdatewhen : '',
+ 0,
+ $_facrec->lines[$i]->info_bits,
+ 'HT',
+ 0,
+ $_facrec->lines[$i]->rang,
+ false,
+ $_facrec->lines[$i]->array_options,
+ $_facrec->lines[$i]->fk_unit,
+ 0,
+ 0,
+ $_facrec->lines[$i]->ref_supplier,
+ $_facrec->lines[$i]->special_code,
+ 0,
+ 0
+ );
+ if ($result_insert < 0) {
+ $error++;
+ $this->error = $this->db->error();
+ break;
+ }
+ }
+ }
+
+
// Update total price
$result = $this->update_price();
if ($result > 0) {
@@ -674,6 +885,7 @@ class FactureFournisseur extends CommonInvoice
$sql .= " t.fk_user_author,";
$sql .= " t.fk_user_valid,";
$sql .= " t.fk_facture_source,";
+ $sql .= " t.fk_fac_rec_source,";
$sql .= " t.fk_projet as fk_project,";
$sql .= " t.fk_cond_reglement,";
$sql .= " t.fk_account,";
@@ -741,6 +953,7 @@ class FactureFournisseur extends CommonInvoice
$this->author = $obj->fk_user_author;
$this->fk_user_valid = $obj->fk_user_valid;
$this->fk_facture_source = $obj->fk_facture_source;
+ $this->fk_fac_rec_source = $obj->fk_fac_rec_source;
$this->fk_project = $obj->fk_project;
$this->cond_reglement_id = $obj->fk_cond_reglement;
$this->cond_reglement_code = $obj->cond_reglement_code;
@@ -2418,17 +2631,13 @@ class FactureFournisseur extends CommonInvoice
// phpcs:enable
global $conf, $langs;
- $clause = " WHERE";
-
- $sql = 'SELECT ff.rowid, ff.date_lim_reglement as datefin, ff.fk_statut, ff.total_ht';
+ $sql = 'SELECT ff.rowid, ff.date_lim_reglement as datefin, ff.fk_statut';
$sql .= ' FROM '.MAIN_DB_PREFIX.'facture_fourn as ff';
if (empty($user->rights->societe->client->voir) && !$user->socid) {
- $sql .= " JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON ff.fk_soc = sc.fk_soc";
- $sql .= " WHERE sc.fk_user = ".((int) $user->id);
- $clause = " AND";
+ $sql .= " JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON ff.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
}
- $sql .= $clause.' ff.paye=0';
- $sql .= ' AND ff.fk_statut = '.self::STATUS_VALIDATED;
+ $sql .= ' WHERE ff.paye = 0';
+ $sql .= ' AND ff.fk_statut > 0';
$sql .= " AND ff.entity = ".$conf->entity;
if ($user->socid) {
$sql .= ' AND ff.fk_soc = '.((int) $user->socid);
@@ -2487,7 +2696,7 @@ class FactureFournisseur extends CommonInvoice
*/
public function getNomUrl($withpicto = 0, $option = '', $max = 0, $short = 0, $moretitle = '', $notooltip = 0, $save_lastsearch_value = -1, $addlinktonotes = 0)
{
- global $langs, $conf, $user;
+ global $langs, $conf, $user, $hookmanager;
$result = '';
@@ -2605,7 +2814,15 @@ class FactureFournisseur extends CommonInvoice
$result .= '';
}
}
-
+ global $action;
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) {
+ $result = $hookmanager->resPrint;
+ } else {
+ $result .= $hookmanager->resPrint;
+ }
return $result;
}
@@ -3412,8 +3629,8 @@ class SupplierInvoiceLine extends CommonObjectLine
$this->db->begin();
$sql = "UPDATE ".MAIN_DB_PREFIX."facture_fourn_det SET";
- $sql .= " description ='".$this->db->escape($this->description)."'";
- $sql .= ", ref ='".$this->db->escape($this->ref_supplier ? $this->ref_supplier : $this->ref)."'";
+ $sql .= " description = '".$this->db->escape($this->description)."'";
+ $sql .= ", ref = '".$this->db->escape($this->ref_supplier ? $this->ref_supplier : $this->ref)."'";
$sql .= ", date_start = ".($this->date_start != '' ? "'".$this->db->idate($this->date_start)."'" : "null");
$sql .= ", date_end = ".($this->date_end != '' ? "'".$this->db->idate($this->date_end)."'" : "null");
$sql .= ", pu_ht = ".price2num($this->pu_ht);
diff --git a/htdocs/fourn/class/fournisseur.product.class.php b/htdocs/fourn/class/fournisseur.product.class.php
index e20add0bb9d..cb9416e3da2 100644
--- a/htdocs/fourn/class/fournisseur.product.class.php
+++ b/htdocs/fourn/class/fournisseur.product.class.php
@@ -1092,7 +1092,7 @@ class ProductFournisseur extends Product
*/
public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
{
- global $db, $conf, $langs;
+ global $db, $conf, $langs, $hookmanager;
if (!empty($conf->dol_no_mouse_hover)) {
$notooltip = 1; // Force disable tooltips
@@ -1227,6 +1227,15 @@ class ProductFournisseur extends Product
$result .= $linkend;
//if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
+ global $action;
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) {
+ $result = $hookmanager->resPrint;
+ } else {
+ $result .= $hookmanager->resPrint;
+ }
return $result;
}
diff --git a/htdocs/fourn/class/paiementfourn.class.php b/htdocs/fourn/class/paiementfourn.class.php
index de9aa4eade9..75984c94f99 100644
--- a/htdocs/fourn/class/paiementfourn.class.php
+++ b/htdocs/fourn/class/paiementfourn.class.php
@@ -594,7 +594,7 @@ class PaiementFourn extends Paiement
*/
public function getNomUrl($withpicto = 0, $option = '', $mode = 'withlistofinvoices', $notooltip = 0, $morecss = '')
{
- global $langs;
+ global $langs, $conf, $hookmanager;
$result = '';
@@ -639,6 +639,15 @@ class PaiementFourn extends Paiement
}
$result .= $linkend;
+ global $action;
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) {
+ $result = $hookmanager->resPrint;
+ } else {
+ $result .= $hookmanager->resPrint;
+ }
return $result;
}
diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php
index ec4ea692f78..35e5257fce0 100644
--- a/htdocs/fourn/commande/card.php
+++ b/htdocs/fourn/commande/card.php
@@ -88,7 +88,7 @@ $datelivraison = dol_mktime(GETPOST('liv_hour', 'int'), GETPOST('liv_min', 'int'
// Security check
-if ($user->socid) {
+if (!empty($user->socid)) {
$socid = $user->socid;
}
@@ -162,6 +162,8 @@ if (!empty($conf->projet->enabled)) {
$caneditproject = empty($conf->global->SUPPLIER_ORDER_FORBID_EDIT_PROJECT) || ($object->statut == CommandeFournisseur::STATUS_DRAFT && preg_match('/^[\(]?PROV/i', $object->ref));
}
+$error = 0;
+
/*
* Actions
@@ -181,7 +183,7 @@ if (empty($reshook)) {
if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
$backtopage = $backurlforlist;
} else {
- $backtopage = DOL_URL_ROOT.'/fourn/commande/card.php?id='.($id > 0 ? $id : '__ID__');
+ $backtopage = DOL_URL_ROOT.'/fourn/commande/card.php?id='.((!empty($id) && $id > 0) ? $id : '__ID__');
}
}
}
@@ -410,22 +412,27 @@ if (empty($reshook)) {
// Set if we used free entry or predefined product
$predef = '';
$product_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : '');
+ $price_ht = price2num(GETPOST('price_ht'), 'MU', 2);
+ $price_ht_devise = price2num(GETPOST('multicurrency_price_ht'), 'CU', 2);
$date_start = dol_mktime(GETPOST('date_start'.$predef.'hour'), GETPOST('date_start'.$predef.'min'), GETPOST('date_start'.$predef.'sec'), GETPOST('date_start'.$predef.'month'), GETPOST('date_start'.$predef.'day'), GETPOST('date_start'.$predef.'year'));
$date_end = dol_mktime(GETPOST('date_end'.$predef.'hour'), GETPOST('date_end'.$predef.'min'), GETPOST('date_end'.$predef.'sec'), GETPOST('date_end'.$predef.'month'), GETPOST('date_end'.$predef.'day'), GETPOST('date_end'.$predef.'year'));
$prod_entry_mode = GETPOST('prod_entry_mode');
if ($prod_entry_mode == 'free') {
$idprod = 0;
- $price_ht = price2num(GETPOST('price_ht'), 'MU', 2);
- $tva_tx = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0);
} else {
$idprod = GETPOST('idprod', 'int');
- $price_ht = price2num(GETPOST('price_ht'), 'MU', 2);
- $tva_tx = '';
}
+ $tva_tx = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0); // Can be '1.2' or '1.2 (CODE)'
+
+ $price_ttc = price2num(GETPOST('price_ttc'), 'MU', 2);
+ $price_ttc_devise = price2num(GETPOST('multicurrency_price_ttc'), 'CU', 2);
$qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS');
- $remise_percent = price2num(GETPOST('remise_percent'.$predef), 2);
- $price_ht_devise = price2num(GETPOST('multicurrency_price_ht'), 'CU', 2);
+
+ $remise_percent = (GETPOSTISSET('remise_percent'.$predef) ? price2num(GETPOST('remise_percent'.$predef, 'alpha'), '', 2) : 0);
+ if (empty($remise_percent)) {
+ $remise_percent = 0;
+ }
// Extrafields
$extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
@@ -530,7 +537,7 @@ if (empty($reshook)) {
}
//If text set in desc is the same as product descpription (as now it's preloaded) whe add it only one time
- if ($product_desc==$desc && !empty($conf->global->PRODUIT_AUTOFILL_DESC)) {
+ if (trim($product_desc) == trim($desc) && !empty($conf->global->PRODUIT_AUTOFILL_DESC)) {
$product_desc='';
}
@@ -541,11 +548,17 @@ if (empty($reshook)) {
$desc = dol_concatdesc($desc, $product_desc, '', !empty($conf->global->MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION));
}
+ $ref_supplier = $productsupplier->ref_supplier;
+
$type = $productsupplier->type;
- if ($price_ht != '' || $price_ht_devise != '') {
+ if (GETPOST('price_ht') != '' || GETPOST('price_ht_devise') != '') {
$price_base_type = 'HT';
$pu = price2num($price_ht, 'MU');
- $pu_ht_devise = price2num($price_ht_devise, 'MU');
+ $pu_ht_devise = price2num($price_ht_devise, 'CU');
+ } elseif (GETPOST('price_ttc') != '' || GETPOST('price_ttc_devise') != '') {
+ $price_base_type = 'TTC';
+ $pu = price2num($price_ttc, 'MU');
+ $pu_ht_devise = price2num($price_ttc_devise, 'CU');
} else {
$price_base_type = ($productsupplier->fourn_price_base_type ? $productsupplier->fourn_price_base_type : 'HT');
if (empty($object->multicurrency_code) || ($productsupplier->fourn_multicurrency_code != $object->multicurrency_code)) { // If object is in a different currency and price not in this currency
@@ -554,13 +567,9 @@ if (empty($reshook)) {
} else {
$pu = $productsupplier->fourn_pu;
$pu_ht_devise = $productsupplier->fourn_multicurrency_unitprice;
- /*var_dump($pu);
- var_dump($pu_ht_devise);exit;*/
}
}
- $ref_supplier = $productsupplier->ref_supplier;
-
$tva_tx = get_default_tva($object->thirdparty, $mysoc, $productsupplier->id, GETPOST('idprodfournprice', 'alpha'));
$tva_npr = get_default_npr($object->thirdparty, $mysoc, $productsupplier->id, GETPOST('idprodfournprice', 'alpha'));
if (empty($tva_tx)) {
@@ -621,22 +630,22 @@ if (empty($reshook)) {
$fk_unit = GETPOST('units', 'alpha');
if (!preg_match('/\((.*)\)/', $tva_tx)) {
- $tva_tx = price2num($tva_tx); // When vat is text input field
+ $tva_tx = price2num($tva_tx); // $txtva can have format '5,1' or '5.1' or '5.1(XXX)', we must clean only if '5,1'
}
// Local Taxes
$localtax1_tx = get_localtax($tva_tx, 1, $mysoc, $object->thirdparty);
$localtax2_tx = get_localtax($tva_tx, 2, $mysoc, $object->thirdparty);
- if ($price_ht !== '') {
+ if (GETPOST('price_ht') != '' || GETPOST('price_ht_devise') != '') {
$pu_ht = price2num($price_ht, 'MU'); // $pu_ht must be rounded according to settings
} else {
$pu_ttc = price2num(GETPOST('price_ttc'), 'MU');
$pu_ht = price2num($pu_ttc / (1 + ($tva_tx / 100)), 'MU'); // $pu_ht must be rounded according to settings
}
$price_base_type = 'HT';
- $pu_ht_devise = price2num($price_ht_devise, 'MU');
-
+ $pu_ht_devise = price2num($price_ht_devise, 'CU');
+ // var_dump($pu_ht.' '.$tva_tx.' '.$pu_ttc.' '.$price_base_type.' '.$pu_ht_devise); exit;
$result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, 0, 0, $ref_supplier, $remise_percent, $price_base_type, $pu_ttc, $type, '', '', $date_start, $date_end, $array_options, $fk_unit, $pu_ht_devise);
}
@@ -687,6 +696,7 @@ if (empty($reshook)) {
unset($_POST['np_markRate']);
unset($_POST['dp_desc']);
unset($_POST['idprodfournprice']);
+ unset($_POST['units']);
unset($_POST['date_starthour']);
unset($_POST['date_startmin']);
diff --git a/htdocs/fourn/facture/card-rec.php b/htdocs/fourn/facture/card-rec.php
new file mode 100644
index 00000000000..502d0d124ce
--- /dev/null
+++ b/htdocs/fourn/facture/card-rec.php
@@ -0,0 +1,1644 @@
+
+ * Copyright (C) 2004-2016 Laurent Destailleur
+ * Copyright (C) 2005-2012 Regis Houssin
+ * Copyright (C) 2013 Florian Henry
+ * Copyright (C) 2013 Juanjo Menent
+ * Copyright (C) 2015 Jean-François Ferry
+ * Copyright (C) 2012 Cedric Salvador
+ * Copyright (C) 2015 Alexandre Spangaro
+ * Copyright (C) 2016 Meziane Sof
+ * Copyright (C) 2017-2018 Frédéric France
+ *
+ * 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 .
+ */
+
+/**
+ * \file htdocs/fourn/facture/card-rec.php
+ * \ingroup facture fournisseurs
+ * \brief Page to show predefined invoice
+ */
+
+require '../../main.inc.php';
+require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.facture-rec.class.php';
+require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.product.class.php';
+require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
+require_once DOL_DOCUMENT_ROOT . '/core/class/html.formother.class.php';
+if (! empty($conf->projet->enabled)) {
+ include_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
+}
+require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
+require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
+require_once DOL_DOCUMENT_ROOT . '/core/lib/invoice.lib.php';
+require_once DOL_DOCUMENT_ROOT . '/core/class/extrafields.class.php';
+
+// Load translation files required by the page
+$langs->loadLangs(array('bills', 'companies', 'compta', 'admin', 'other', 'products', 'banks', 'suppliers'));
+
+$action = GETPOST('action', 'alpha');
+$massaction = GETPOST('massaction', 'alpha');
+$show_files = GETPOST('show_files', 'int');
+$confirm = GETPOST('confirm', 'alpha');
+$cancel = GETPOST('cancel', 'alpha');
+$toselect = GETPOST('toselect', 'array');
+$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'supplierinvoicetemplatelist'; // To manage different context of search
+
+$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit;
+$sortfield = GETPOST("sortfield", 'alpha');
+$sortorder = GETPOST("sortorder", 'alpha');
+$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
+
+// Security check
+$id = (GETPOST('facid', 'int') ? GETPOST('facid', 'int') : GETPOST('id', 'int'));
+$lineid = GETPOST('lineid', 'int');
+$title = GETPOST('title', 'alpha');
+$ref_supplier = GETPOST('ref_supplier', 'alpha');
+$projectid = GETPOST('projectid', 'int');
+$year_date_when = GETPOST('year_date_when');
+$month_date_when = GETPOST('month_date_when');
+if ($user->socid) {
+ $socid = $user->socid;
+}
+$objecttype = 'facturefournisseur_rec';
+if ($action == "create" || $action == "add") {
+ $objecttype = '';
+}
+
+if (empty($page) || $page == -1) {
+ $page = 0;
+} // If $page is not defined, or '' or -1
+$offset = $limit * $page;
+if (! $sortorder) {
+ $sortorder = 'DESC';
+}
+if (! $sortfield) {
+ $sortfield = 'f.titre';
+}
+$pageprev = $page - 1;
+$pagenext = $page + 1;
+
+$object = new FactureFournisseurRec($db);
+if (($id > 0 || $title) && $action != 'create' && $action != 'add') {
+ $ret = $object->fetch($id, $title);
+ if (! $ret) {
+ setEventMessages($langs->trans("ErrorRecordNotFound"), null, 'errors');
+ }
+}
+
+// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
+$hookmanager->initHooks(array('supplierinvoicereccard', 'globalcard'));
+$extrafields = new ExtraFields($db);
+
+// fetch optionals attributes and labels
+$extrafields->fetch_name_optionals_label($object->table_element);
+
+$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
+
+$permissionnote = $user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer; // Used by the include of actions_setnotes.inc.php
+$permissiondellink = $user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer;; // Used by the include of actions_dellink.inc.php
+$permissiontoedit = $user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer;; // Used by the include of actions_lineupdonw.inc.php
+
+$usercanread = $user->rights->fournisseur->facture->lire || $user->rights->supplier_invoice->lire;
+$usercancreate = $user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer;
+$usercandelete = $user->rights->fournisseur->facture->supprimer || $user->rights->supplier_invoice->supprimer;
+$usercanvalidate = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($usercancreate)) || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->fournisseur->supplier_invoice_advance->validate)));
+$usercansend = (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->fournisseur->supplier_invoice_advance->send);
+
+$usercanproductignorepricemin = ((! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS));
+$usercancreatemargin = $user->rights->margins->creer;
+$usercanreadallmargin = $user->rights->margins->liretous;
+$usercancreatewithdrarequest = $user->rights->prelevement->bons->creer;
+
+$now = dol_now();
+
+$error = 0;
+
+$result = restrictedArea($user, 'facture', $object->id, $objecttype);
+
+/*
+ * Actions
+ */
+
+if (GETPOST('cancel', 'alpha')) {
+ $action = 'list';
+ $massaction = '';
+}
+if (! GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
+ $massaction = '';
+}
+
+$parameters = array('socid' => $socid);
+$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
+if ($reshook < 0) {
+ setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
+}
+
+if (empty($reshook)) {
+ if (GETPOST('cancel', 'alpha')) {
+ $action = '';
+ }
+
+ // Selection of new fields
+ include DOL_DOCUMENT_ROOT . '/core/actions_changeselectedfields.inc.php';
+
+ // Set note
+ include DOL_DOCUMENT_ROOT . '/core/actions_setnotes.inc.php'; // Must be include, not include_once
+
+ include DOL_DOCUMENT_ROOT . '/core/actions_dellink.inc.php'; // Must be include, not include_once
+
+ include DOL_DOCUMENT_ROOT . '/core/actions_lineupdown.inc.php'; // Must be include, not include_once
+
+ // Create predefined invoice
+ if ($action == 'add') {
+ if (! GETPOST('title', 'alphanohtml')) {
+ setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->trans("Title")), null, 'errors');
+ $action = "create";
+ $error++;
+ }
+
+ $frequency = GETPOST('frequency', 'int');
+ $reyear = GETPOST('reyear', 'int');
+ $remonth = GETPOST('remonth', 'int');
+ $reday = GETPOST('reday', 'int');
+ $rehour = GETPOST('rehour', 'int');
+ $remin = GETPOST('remin', 'int');
+ $nb_gen_max = GETPOST('nb_gen_max', 'int');
+ //if (empty($nb_gen_max)) $nb_gen_max =0;
+
+ if (GETPOST('frequency', 'int')) {
+ if (empty($reyear) || empty($remonth) || empty($reday)) {
+ setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->trans("Date")), null, 'errors');
+ $action = "create";
+ $error++;
+ }
+ }
+
+ if (! $error) {
+ $object->titre = GETPOST('title', 'nohtml'); // deprecated
+ $object->title = GETPOST('title', 'nohtml');
+ $object->fk_project = GETPOST('projectid', 'int');
+ $object->ref_supplier = GETPOST('ref_supplier', 'nohtml');
+
+ $object->note_private = GETPOST('note_private', 'restricthtml');
+ $object->note_public = GETPOST('note_public', 'restricthtml');
+ $object->model_pdf = GETPOST('modelpdf', 'alpha');
+ $object->usenewprice = GETPOST('usenewprice', 'alpha');
+
+ $object->frequency = $frequency;
+ $object->unit_frequency = GETPOST('unit_frequency', 'alpha');
+ $object->nb_gen_max = $nb_gen_max;
+ $object->auto_validate = GETPOST('auto_validate', 'int');
+ $object->generate_pdf = GETPOST('generate_pdf', 'int');
+
+ $date_next_execution = dol_mktime($rehour, $remin, 0, $remonth, $reday, $reyear);
+ $object->date_when = $date_next_execution;
+
+ $db->begin();
+
+ $oldinvoice = new FactureFournisseur($db);
+ $oldinvoice->fetch(GETPOST('facid', 'int'));
+
+ $object->cond_reglement_id = $oldinvoice->cond_reglement_id;
+ $object->cond_reglement_code = $oldinvoice->cond_reglement_code;
+ $object->cond_reglement_label = $oldinvoice->cond_reglement_label;
+ $object->cond_reglement_doc = $oldinvoice->cond_reglement_doc;
+ $object->mode_reglement_id = $oldinvoice->mode_reglement_id;
+ $object->mode_reglement_code = $oldinvoice->mode_reglement_code;
+
+ $result = $object->create($user, $oldinvoice->id);
+ if ($result > 0) {
+ $result = $oldinvoice->delete($user, 1);
+ if ($result < 0) {
+ $error++;
+ setEventMessages($oldinvoice->error, $oldinvoice->errors, 'errors');
+ $action = "create";
+ }
+ } else {
+ $error++;
+ setEventMessages($object->error, $object->errors, 'errors');
+ $action = "create";
+ }
+
+ if (! $error) {
+ $db->commit();
+
+ header("Location: " . $_SERVER['PHP_SELF'] . '?facid=' . $object->id);
+ exit;
+ } else {
+ $db->rollback();
+
+ $error++;
+ setEventMessages($object->error, $object->errors, 'errors');
+ $action = "create";
+ }
+ }
+ }
+
+ // Delete
+ //TODO : Droits
+ if ($action == 'confirm_deleteinvoice' && $confirm == 'yes' && ($user->rights->fournisseur->facture->supprimer || $user->rights->supplier_invoice->supprimer)) {
+ $object->delete($user);
+
+ header('Location: ' . DOL_URL_ROOT . '/fourn/facture/list-rec.php');
+ exit;
+ }
+
+ // Update field
+ // Set condition
+ if ($action == 'setconditions' && $usercancreate) {
+ $result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'));
+ } elseif ($action == 'setmode' && $usercancreate) {
+ // Set mode
+ $result = $object->setPaymentMethods(GETPOST('mode_reglement_id', 'int'));
+ } elseif ($action == 'classin' && $usercancreate) {
+ // Set project
+ $object->setProject(GETPOST('projectid', 'int'));
+ } elseif ($action == 'setref_supplier' && $usercancreate) {
+ $result = $object->setValueFrom('ref_supplier', $ref_supplier, '', null, 'text', '', $user);
+
+ if ($result <= 0) {
+ $error++;
+ if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
+ $langs->load("errors");
+ setEventMessages($langs->trans('ErrorRefAlreadyExists', $ref_supplier), null, 'errors');
+ } else {
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
+ }
+ } elseif ($action == 'settitle' && $usercancreate) {
+ $result = $object->setValueFrom('titre', $title, '', null, 'text', '', $user);
+
+ if ($result > 0) {
+ $object->titre = $title;
+ $object->title = $title;
+ $object->ref = $object->title;
+ } else {
+ $error++;
+ if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
+ $langs->load("errors");
+ setEventMessages($langs->trans('ErrorTitreAlreadyExists', $title), null, 'errors');
+ } else {
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
+ }
+ } elseif ($action == 'setbankaccount' && $usercancreate) {
+ // Set bank account
+ $result = $object->setBankAccount(GETPOST('fk_account', 'int'));
+ } elseif ($action == 'setfrequency' && $usercancreate) {
+ // Set frequency and unit frequency
+ $object->setFrequencyAndUnit(GETPOST('frequency', 'int'), GETPOST('unit_frequency', 'alpha'));
+ } elseif ($action == 'setdate_when' && $usercancreate) {
+ // Set next date of execution
+ $date = dol_mktime(GETPOST('date_whenhour'), GETPOST('date_whenmin'), 0, GETPOST('date_whenmonth'), GETPOST('date_whenday'), GETPOST('date_whenyear'));
+ if (! empty($date)) {
+ $object->setNextDate($date);
+ }
+ } elseif ($action == 'setnb_gen_max' && $usercancreate) {
+ // Set max period
+ $object->setMaxPeriod(GETPOST('nb_gen_max', 'int'));
+ } elseif ($action == 'setauto_validate' && $usercancreate) {
+ // Set auto validate
+ $object->setAutoValidate(GETPOST('auto_validate', 'int'));
+ } elseif ($action == 'setgenerate_pdf' && $usercancreate) {
+ // Set generate pdf
+ $object->setGeneratepdf(GETPOST('generate_pdf', 'int'));
+ } elseif ($action == 'setmodelpdf' && $usercancreate) {
+ // Set model pdf
+ $object->setModelpdf(GETPOST('modelpdf', 'alpha'));
+ } elseif ($action == 'disable' && $usercancreate) {
+ // Set status disabled
+ $db->begin();
+
+ $object->fetch($id);
+
+ $res = $object->setValueFrom('suspended', 1);
+ if ($res <= 0) {
+ $error++;
+ }
+
+ if (! $error) {
+ $db->commit();
+ } else {
+ $db->rollback();
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
+ } elseif ($action == 'enable' && $usercancreate) {
+ // Set status enabled
+ $db->begin();
+
+ $object->fetch($id);
+
+ $res = $object->setValueFrom('suspended', 0);
+ if ($res <= 0) {
+ $error++;
+ }
+
+ if (! $error) {
+ $db->commit();
+ } else {
+ $db->rollback();
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
+ } elseif ($action == 'setmulticurrencycode' && $usercancreate) {
+ // Multicurrency Code
+ $result = $object->setMulticurrencyCode(GETPOST('multicurrency_code', 'alpha'));
+ } elseif ($action == 'setmulticurrencyrate' && $usercancreate) {
+ // Multicurrency rate
+ $result = $object->setMulticurrencyRate(price2num(GETPOST('multicurrency_tx')), GETPOST('calculation_mode', 'int'));
+ } elseif ($action == 'setlibelle' && $usercancreate) {
+ // Set label
+ $object->fetch($id);
+ $object->libelle = GETPOST('libelle');
+ $result = $object->update($user);
+
+ if ($result < 0) {
+ dol_print_error($db);
+ }
+ }
+
+ // Delete line
+ if ($action == 'confirm_deleteline' && $confirm == 'yes' && $usercancreate) {
+ $object->fetch($id);
+ $object->fetch_thirdparty();
+
+ $db->begin();
+
+ $line = new FactureFournisseurLigneRec($db);
+
+ // For triggers
+ $line->id = $lineid;
+
+ if ($line->delete($user) > 0) {
+ $result = $object->update_price(1);
+
+ if ($result > 0) {
+ $db->commit();
+ $object->fetch($object->id); // Reload lines
+ } else {
+ $db->rollback();
+ setEventMessages($db->lasterror(), null, 'errors');
+ }
+ } else {
+ $db->rollback();
+ setEventMessages($line->error, $line->errors, 'errors');
+ }
+ } elseif ($action == 'update_extras') {
+ $object->oldcopy = dol_clone($object);
+
+ // Fill array 'array_options' with data from update form
+ $ret = $extrafields->setOptionalsFromPost(null, $object, GETPOST('attribute', 'restricthtml'));
+ if ($ret < 0) {
+ $error++;
+ }
+
+ if (! $error) {
+ $result = $object->insertExtraFields('BILLREC_MODIFY');
+ if ($result < 0) {
+ setEventMessages($object->error, $object->errors, 'errors');
+ $error++;
+ }
+ }
+ }
+
+ // Add a new line
+ if ($action == 'addline' && $usercancreate) {
+ $langs->load('errors');
+ $error = 0;
+
+ // Set if we used free entry or predefined product
+
+ $product_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : '');
+ $price_ht = price2num(GETPOST('price_ht'), 'MU', 2);
+ $price_ht_devise = price2num(GETPOST('multicurrency_price_ht'), 'CU', 2);
+ $prod_entry_mode = GETPOST('prod_entry_mode', 'alpha');
+ if ($prod_entry_mode == 'free') {
+ $idprod = 0;
+ $tva_tx = (GETPOST('tva_tx', 'alpha') ? GETPOST('tva_tx', 'alpha') : 0);
+ $ref_fournisseur = (GETPOSTISSET('fourn_ref') ? GETPOST('fourn_ref', 'restricthtml') : '');
+ } else {
+ $idprod = GETPOST('idprod', 'int');
+ $tva_tx = '';
+ }
+
+ $qty = price2num(GETPOST('qty' . $predef, 'alpha'), 'MS', 2);
+ $remise_percent = price2num(GETPOST('remise_percent' . $predef), '', 2);
+
+ // Extrafields
+ $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
+ $array_options = $extrafields->getOptionalsFromPost($object->table_element_line, $predef);
+ // Unset extrafield
+ if (is_array($extralabelsline)) {
+ // Get extra fields
+ foreach ($extralabelsline as $key => $value) {
+ unset($_POST["options_" . $key . $predef]);
+ }
+ }
+
+ if ((empty($idprod) || $idprod < 0) && ($price_ht < 0) && ($qty < 0)) {
+ setEventMessages($langs->trans('ErrorBothFieldCantBeNegative', $langs->transnoentitiesnoconv('UnitPriceHT'), $langs->transnoentitiesnoconv('Qty')), null, 'errors');
+ $error++;
+ }
+ if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && GETPOST('type') < 0) {
+ setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors');
+ $error++;
+ }
+ if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && (! ($price_ht >= 0) || $price_ht == '')) { // Unit price can be 0 but not ''
+ setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("UnitPriceHT")), null, 'errors');
+ $error++;
+ }
+ if ($qty == '') {
+ setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
+ $error++;
+ }
+ if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && empty($product_desc)) {
+ setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), null, 'errors');
+ $error++;
+ }
+ if ($qty < 0) {
+ $langs->load("errors");
+ setEventMessages($langs->trans('ErrorQtyForCustomerInvoiceCantBeNegative'), null, 'errors');
+ $error++;
+ }
+
+ if ($prod_entry_mode != 'free' && empty($error)) { // With combolist mode idprodfournprice is > 0 or -1. With autocomplete, idprodfournprice is > 0 or ''
+ $productsupplier = new ProductFournisseur($db);
+
+ $idprod = 0;
+ if (GETPOST('idprodfournprice', 'alpha') == -1 || GETPOST('idprodfournprice', 'alpha') == '') {
+ $idprod = -99; // Same behaviour than with combolist. When not select idprodfournprice is now -99 (to avoid conflict with next action that may return -1, -2, ...)
+ }
+ $reg = array();
+ if (preg_match('/^idprod_([0-9]+)$/', GETPOST('idprodfournprice', 'alpha'), $reg)) {
+ $idprod = (int) $reg[1];
+ $res = $productsupplier->fetch($idprod); // Load product from its id
+ // Call to init some price properties of $productsupplier
+ // So if a supplier price already exists for another thirdparty (first one found), we use it as reference price
+ if (! empty($conf->global->SUPPLIER_TAKE_FIRST_PRICE_IF_NO_PRICE_FOR_CURRENT_SUPPLIER)) {
+ $fksoctosearch = 0;
+ $productsupplier->get_buyprice(0, -1, $idprod, 'none', $fksoctosearch); // We force qty to -1 to be sure to find if a supplier price exist
+ if ($productsupplier->fourn_socid != $socid) { // The price we found is for another supplier, so we clear supplier price
+ $productsupplier->ref_supplier = '';
+ }
+ } else {
+ $fksoctosearch = $object->thirdparty->id;
+ $productsupplier->get_buyprice(0, -1, $idprod, 'none', $fksoctosearch); // We force qty to -1 to be sure to find if a supplier price exist
+ }
+ } elseif (GETPOST('idprodfournprice', 'alpha') > 0) {
+ $qtytosearch = $qty; // Just to see if a price exists for the quantity. Not used to found vat.
+ $idprod = $productsupplier->get_buyprice(GETPOST('idprodfournprice', 'alpha'), $qtytosearch);
+ $res = $productsupplier->fetch($idprod);
+ $ref_fournisseur = $productsupplier->ref_supplier;
+ }
+ }
+
+ if (! $error && ($qty >= 0) && (! empty($product_desc) || (! empty($idprod) && $idprod > 0))) {
+ $ret = $object->fetch($id);
+ if ($ret < 0) {
+ dol_print_error($db, $object->error);
+ exit();
+ }
+ $ret = $object->fetch_thirdparty();
+
+ // Clean parameters
+ $date_start = dol_mktime(GETPOST('date_start' . $predef . 'hour'), GETPOST('date_start' . $predef . 'min'), GETPOST('date_start' . $predef . 'sec'), GETPOST('date_start' . $predef . 'month'), GETPOST('date_start' . $predef . 'day'), GETPOST('date_start' . $predef . 'year'));
+ $date_end = dol_mktime(GETPOST('date_end' . $predef . 'hour'), GETPOST('date_end' . $predef . 'min'), GETPOST('date_end' . $predef . 'sec'), GETPOST('date_end' . $predef . 'month'), GETPOST('date_end' . $predef . 'day'), GETPOST('date_end' . $predef . 'year'));
+ $price_base_type = (GETPOST('price_base_type', 'alpha') ? GETPOST('price_base_type', 'alpha') : 'HT');
+
+ // Define special_code for special lines
+ $special_code = 0;
+ // if (empty($_POST['qty'])) $special_code=3; // Options should not exists on invoices
+
+ // Ecrase $pu par celui du produit
+ // Ecrase $desc par celui du produit
+ // Ecrase $tva_tx par celui du produit
+ // Ecrase $base_price_type par celui du produit
+ // Replaces $fk_unit with the product's
+ if (! empty($idprod) && $idprod > 0) {
+ $prod = new Product($db);
+ $prod->fetch($idprod);
+
+ $label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : '');
+
+ // Update if prices fields are defined
+ $tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
+ $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
+ if (empty($tva_tx)) {
+ $tva_npr = 0;
+ }
+
+ // Search the correct price into loaded array product_price_by_qty using id of array retrieved into POST['pqp'].
+ $pqp = (GETPOST('pbq', 'int') ? GETPOST('pbq', 'int') : 0);
+
+ $datapriceofproduct = $prod->getSellPrice($mysoc, $object->thirdparty, $pqp);
+
+ $pu_ht = $datapriceofproduct['pu_ht'];
+ $pu_ttc = $datapriceofproduct['pu_ttc'];
+ $price_min = $datapriceofproduct['price_min'];
+ $price_base_type = $datapriceofproduct['price_base_type'];
+ $tva_tx = $datapriceofproduct['tva_tx'];
+ $tva_npr = $datapriceofproduct['tva_npr'];
+
+ $tmpvat = price2num(preg_replace('/\s*\(.*\)/', '', $tva_tx));
+ $tmpprodvat = price2num(preg_replace('/\s*\(.*\)/', '', $prod->tva_tx));
+
+ // if price ht was forced (ie: from gui when calculated by margin rate and cost price). TODO Why this ?
+ if (! empty($price_ht)) {
+ $pu_ht = price2num($price_ht, 'MU');
+ $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
+ } elseif ($tmpvat != $tmpprodvat) {
+ // On reevalue prix selon taux tva car taux tva transaction peut etre different
+ // de ceux du produit par defaut (par exemple si pays different entre vendeur et acheteur).
+ if ($price_base_type != 'HT') {
+ $pu_ht = price2num($pu_ttc / (1 + ($tmpvat / 100)), 'MU');
+ } else {
+ $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
+ }
+ }
+
+ $desc = '';
+
+ // Define output language
+ if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
+ $outputlangs = $langs;
+ $newlang = '';
+ if (empty($newlang) && GETPOST('lang_id', 'aZ09')) {
+ $newlang = GETPOST('lang_id', 'aZ09');
+ }
+ if (empty($newlang)) {
+ $newlang = $object->thirdparty->default_lang;
+ }
+ if (! empty($newlang)) {
+ $outputlangs = new Translate("", $conf);
+ $outputlangs->setDefaultLang($newlang);
+ }
+
+ $desc = (! empty($prod->multilangs [$outputlangs->defaultlang] ["description"])) ? $prod->multilangs [$outputlangs->defaultlang] ["description"] : $prod->description;
+ } else {
+ $desc = $prod->description;
+ }
+
+ $desc = dol_concatdesc($desc, $product_desc);
+
+ // Add custom code and origin country into description
+ if (empty($conf->global->MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE) && (! empty($prod->customcode) || ! empty($prod->country_code))) {
+ $tmptxt = '(';
+ // Define output language
+ if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
+ $outputlangs = $langs;
+ $newlang = '';
+ if (empty($newlang) && GETPOST('lang_id', 'alpha')) {
+ $newlang = GETPOST('lang_id', 'alpha');
+ }
+ if (empty($newlang)) {
+ $newlang = $object->thirdparty->default_lang;
+ }
+ if (! empty($newlang)) {
+ $outputlangs = new Translate("", $conf);
+ $outputlangs->setDefaultLang($newlang);
+ $outputlangs->load('products');
+ }
+ if (! empty($prod->customcode)) {
+ $tmptxt .= $outputlangs->transnoentitiesnoconv("CustomCode") . ': ' . $prod->customcode;
+ }
+ if (! empty($prod->customcode) && ! empty($prod->country_code)) {
+ $tmptxt .= ' - ';
+ }
+ if (! empty($prod->country_code)) {
+ $tmptxt .= $outputlangs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, 0, $db, $outputlangs, 0);
+ }
+ } else {
+ if (! empty($prod->customcode)) {
+ $tmptxt .= $langs->transnoentitiesnoconv("CustomCode") . ': ' . $prod->customcode;
+ }
+ if (! empty($prod->customcode) && ! empty($prod->country_code)) {
+ $tmptxt .= ' - ';
+ }
+ if (! empty($prod->country_code)) {
+ $tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, 0, $db, $langs, 0);
+ }
+ }
+ $tmptxt .= ')';
+ $desc = dol_concatdesc($desc, $tmptxt);
+ }
+
+ $type = $prod->type;
+ $fk_unit = $prod->fk_unit;
+ } else {
+ $pu_ht = price2num($price_ht, 'MU');
+ $pu_ttc = price2num(GETPOST('price_ttc'), 'MU');
+ $tva_npr = (preg_match('/\*/', $tva_tx) ? 1 : 0);
+ $tva_tx = str_replace('*', '', $tva_tx);
+ if (empty($tva_tx)) {
+ $tva_npr = 0;
+ }
+ $desc = $product_desc;
+ $type = GETPOST('type');
+ $fk_unit = GETPOST('units', 'alpha');
+ }
+
+ $date_start_fill = ! empty(GETPOST('date_start_fill', 'int')) ? GETPOST('date_start_fill', 'int') : null;
+ $date_end_fill = ! empty(GETPOST('date_end_fill', 'int')) ? GETPOST('date_end_fill', 'int') : null;
+
+ // Margin
+ $fournprice = price2num(GETPOST('fournprice' . $predef) ? GETPOST('fournprice' . $predef) : '');
+ $buyingprice = price2num(GETPOST('buying_price' . $predef) != '' ? GETPOST('buying_price' . $predef) : ''); // If buying_price is '0', we must keep this value
+
+ // Local Taxes
+ $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty, $mysoc, $tva_npr);
+ $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty, $mysoc, $tva_npr);
+ $info_bits = 0;
+ if ($tva_npr) {
+ $info_bits |= 0x01;
+ }
+
+ //To set vars in float type to avoid non-numeric warnings
+ $pu_ht = (float) price2num($pu_ht);
+ $remise_percent = (float) price2num($remise_percent);
+
+ $price_min = (float) price2num($price_min);
+ if ($usercanproductignorepricemin && (! empty($price_min) && ($pu_ht * (1 - $remise_percent / 100) < $price_min))) {
+ $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
+ setEventMessages($mesg, null, 'errors');
+ } else {
+ // Insert line
+ $result = $object->addline($idprod, $ref_fournisseur, $label, $desc, $pu_ht, $pu_ttc, $qty, $remise_percent, $tva_tx, $localtax1_tx, $localtax2_tx, $price_base_type, $type, $date_start_fill, $date_end_fill, $info_bits, $special_code, -1, $fk_unit);
+
+ if ($result > 0) {
+ $object->fetch($object->id); // Reload lines
+
+ unset($_POST['prod_entry_mode']);
+ unset($_POST['qty']);
+ unset($_POST['type']);
+ unset($_POST['remise_percent']);
+ unset($_POST['price_ht']);
+ unset($_POST['multicurrency_price_ht']);
+ unset($_POST['price_ttc']);
+ unset($_POST['tva_tx']);
+ unset($_POST['product_ref']);
+ unset($_POST['product_label']);
+ unset($_POST['product_desc']);
+ unset($_POST['fournprice']);
+ unset($_POST['buying_price']);
+ unset($_POST['np_marginRate']);
+ unset($_POST['np_markRate']);
+ unset($_POST['dp_desc']);
+ unset($_POST['idprod']);
+ unset($_POST['units']);
+ unset($_POST['date_starthour']);
+ unset($_POST['date_startmin']);
+ unset($_POST['date_startsec']);
+ unset($_POST['date_startday']);
+ unset($_POST['date_startmonth']);
+ unset($_POST['date_startyear']);
+ unset($_POST['date_endhour']);
+ unset($_POST['date_endmin']);
+ unset($_POST['date_endsec']);
+ unset($_POST['date_endday']);
+ unset($_POST['date_endmonth']);
+ unset($_POST['date_endyear']);
+ unset($_POST['date_start_fill']);
+ unset($_POST['date_end_fill']);
+ unset($_POST['situations']);
+ unset($_POST['progress']);
+ } else {
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
+
+ $action = '';
+ }
+ }
+ } elseif ($action == 'updateline' && $usercancreate && ! GETPOST('cancel', 'alpha')) {
+ if (! $object->fetch($id) > 0) {
+ dol_print_error($db);
+ }
+ $object->fetch_thirdparty();
+
+ // Clean parameters
+ $date_start = '';
+ $date_end = '';
+ $description = dol_htmlcleanlastbr(GETPOST('product_desc', 'restricthtml') ? GETPOST('product_desc', 'restricthtml') : GETPOST('desc', 'restricthtml'));
+ $ref_fourn = GETPOST('fourn_ref', 'alpha');
+ $pu_ht = price2num(GETPOST('price_ht'), '', 2);
+ $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0);
+ $qty = GETPOST('qty');
+ $pu_ht_devise = price2num(GETPOST('multicurrency_subprice'), '', 2);
+
+ // Define info_bits
+ $info_bits = 0;
+ if (preg_match('/\*/', $vat_rate)) {
+ $info_bits |= 0x01;
+ }
+
+ // Define vat_rate
+ $vat_rate = str_replace('*', '', $vat_rate);
+ $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty);
+ $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty);
+
+ // Extrafields
+ $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
+ $array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
+
+ $objectline = new FactureFournisseurLigneRec($db);
+ if ($objectline->fetch(GETPOST('lineid', 'int'))) {
+ $objectline->array_options = $array_options;
+ $result = $objectline->insertExtraFields();
+ if ($result < 0) {
+ setEventMessages($langs->trans('Error') . $result, null, 'errors');
+ }
+ }
+
+ $position = ($objectline->rang >= 0 ? $objectline->rang : 0);
+
+ // Unset extrafield
+ if (is_array($extralabelsline)) {
+ // Get extra fields
+ foreach ($extralabelsline as $key => $value) {
+ unset($_POST["options_" . $key]);
+ }
+ }
+
+ // Define special_code for special lines
+ $special_code = GETPOST('special_code', 'int');
+ if (! GETPOST('qty', 'alpha')) {
+ $special_code = 3;
+ }
+
+ $remise_percent = price2num(GETPOST('remise_percent'), '', 2);
+
+ // Check minimum price
+ $productid = GETPOST('productid', 'int');
+ if (! empty($productid)) {
+ $product = new Product($db);
+ $product->fetch($productid);
+
+ $type = $product->type;
+
+ $price_min = $product->price_min;
+ if (! empty($conf->global->PRODUIT_MULTIPRICES) && ! empty($object->thirdparty->price_level)) {
+ $price_min = $product->multiprices_min[$object->thirdparty->price_level];
+ }
+
+ $label = $product->label;
+
+ // Check price is not lower than minimum (check is done only for standard or replacement invoices)
+ if (((! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS)) && $price_min && (price2num($pu_ht) * (1 - $remise_percent / 100) < price2num($price_min))) {
+ setEventMessages($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency)), null, 'errors');
+ $error++;
+ }
+ } else {
+ $type = GETPOST('type', 'int');
+ $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
+
+ // Check parameters
+ if (GETPOST('type', 'int') < 0) {
+ setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
+ $error++;
+ }
+ }
+ if ($qty < 0) {
+ $langs->load("errors");
+ setEventMessages($langs->trans('ErrorQtyForCustomerInvoiceCantBeNegative'), null, 'errors');
+ $error++;
+ }
+
+ $date_start_fill = ! empty(GETPOST('date_start_fill', 'int')) ? GETPOST('date_start_fill', 'int') : 'NULL';
+ $date_end_fill = ! empty(GETPOST('date_end_fill', 'int')) ? GETPOST('date_end_fill', 'int') : 'NULL';
+
+ // Update line
+ if (! $error) {
+ $result = $object->updateline(GETPOST('lineid', 'int'), GETPOST('productid', 'int'), $ref_fourn, $label, $description, $pu_ht, $qty, $remise_percent, $vat_rate, $localtax1_rate, $localtax1_rate, 'HT', $type, $date_start_fill, $date_end_fill, $info_bits, $special_code, -1);
+ if ($result >= 0) {
+ $object->fetch($object->id); // Reload lines
+
+ unset($_POST['qty']);
+ unset($_POST['type']);
+ unset($_POST['productid']);
+ unset($_POST['remise_percent']);
+ unset($_POST['price_ht']);
+ unset($_POST['multicurrency_price_ht']);
+ unset($_POST['price_ttc']);
+ unset($_POST['tva_tx']);
+ unset($_POST['product_ref']);
+ unset($_POST['product_label']);
+ unset($_POST['product_desc']);
+ unset($_POST['fournprice']);
+ unset($_POST['buying_price']);
+ unset($_POST['np_marginRate']);
+ unset($_POST['np_markRate']);
+ unset($_POST['dp_desc']);
+ unset($_POST['idprod']);
+ unset($_POST['units']);
+ unset($_POST['date_starthour']);
+ unset($_POST['date_startmin']);
+ unset($_POST['date_startsec']);
+ unset($_POST['date_startday']);
+ unset($_POST['date_startmonth']);
+ unset($_POST['date_startyear']);
+ unset($_POST['date_endhour']);
+ unset($_POST['date_endmin']);
+ unset($_POST['date_endsec']);
+ unset($_POST['date_endday']);
+ unset($_POST['date_endmonth']);
+ unset($_POST['date_endyear']);
+ unset($_POST['situations']);
+ unset($_POST['progress']);
+ } else {
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
+ }
+ }
+}
+
+/*
+ * View
+ */
+
+$help_url = '';
+llxHeader('', $langs->trans("RepeatableSupplierInvoice"), $help_url);
+
+$form = new Form($db);
+$formother = new FormOther($db);
+if (! empty($conf->projet->enabled)) {
+ $formproject = new FormProjets($db);
+}
+$companystatic = new Societe($db);
+$invoicerectmp = new FactureFournisseurRec($db);
+
+$now = dol_now();
+$nowlasthour = dol_get_last_hour($now);
+
+/*
+ * Create mode
+ */
+if ($action == 'create') {
+ print load_fiche_titre($langs->trans("CreateRepeatableInvoice"), '', 'bill');
+
+ $object = new FactureFournisseur($db); // Source invoice
+ $product_static = new Product($db);
+
+ if ($object->fetch($id) > 0) {
+ $result = $object->fetch_lines();
+
+ print ' ';
+ print "
\n";
+
+ print $form->buttonsSaveCancel("Create");
+
+ print "\n";
+ } else {
+ dol_print_error('', "Error, no invoice " . $object->id);
+ }
+} else {
+ /*
+ * View mode
+ */
+ if ($object->id > 0) {
+ $object->fetch($object->id);
+ $object->fetch_thirdparty();
+
+ // Confirmation de la suppression d'une ligne produit
+ if ($action == 'ask_deleteline') {
+ $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id . '&lineid=' . $lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 'no', 1);
+ }
+
+ // Confirm delete of repeatable invoice
+ if ($action == 'ask_deleteinvoice') {
+ $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('DeleteRepeatableInvoice'), $langs->trans('ConfirmDeleteRepeatableInvoice'), 'confirm_deleteinvoice', '', 'no', 1);
+ }
+
+ print $formconfirm;
+
+ $author = new User($db);
+ $author->fetch($object->user_author);
+
+ $head = supplier_invoice_rec_prepare_head($object);
+
+ print dol_get_fiche_head($head, 'card', $langs->trans('RepeatableInvoice'), -1, 'bill'); // Add a div
+
+ // Recurring invoice content
+
+ $linkback = '' . $langs->trans('BackToList') . ' ';
+
+ $morehtmlref = '';
+ if ($action != 'edittitle') {
+ $morehtmlref .= $form->editfieldkey($object->titre, 'title', $object->titre, $object, $usercancreate, '', '', 0, 2);
+ } else {
+ $morehtmlref .= $form->editfieldval('', 'title', $object->titre, $object, $usercancreate, 'string');
+ }
+ $morehtmlref .= '';
+ //Ref supplier
+ $morehtmlref .= $form->editfieldkey("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $usercancreate, 'string', '', 0, 1);
+ $morehtmlref .= $form->editfieldval("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $usercancreate, 'string', '', null, null, '', 1);
+ // Thirdparty
+ $morehtmlref .= '
' . $langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1);
+
+ // Project
+ if (! empty($conf->projet->enabled)) {
+ $langs->load('projects');
+ $morehtmlref .= '
' . $langs->trans('Project') . ' ';
+ if ($usercancreate) {
+ if ($action != 'classify') {
+ $morehtmlref .= '
' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : ';
+ }
+ if ($action == 'classify') {
+ $morehtmlref .= '
';
+ } else {
+ $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1);
+ }
+ } else {
+ if (! empty($object->fk_project)) {
+ $project = new Project($db);
+ $project->fetch($object->fk_project);
+ $morehtmlref .= ' : ' . $project->getNomUrl(1);
+ if ($project->title) {
+ $morehtmlref .= ' - ' . $project->title;
+ }
+ } else {
+ $morehtmlref .= '';
+ }
+ }
+ }
+ $morehtmlref .= '
';
+
+ $morehtmlright = '';
+
+ dol_banner_tab($object, 'ref', $linkback, 1, 'title', 'none', $morehtmlref, '', 0, '', $morehtmlright);
+
+ print '';
+ print '
';
+ print '
';
+
+ print '
';
+
+ print '' . $langs->trans('Author') . ' ';
+ print $author->getNomUrl(-1);
+ print " ";
+
+ // Label
+ print '';
+ print '' . $form->editfieldkey("Label", 'libelle', $object->libelle, $object, $usercancreate) . ' ';
+ print '' . $form->editfieldval("Label", 'libelle', $object->libelle, $object, $usercancreate) . ' ';
+ print ' ';
+
+ print '' . $langs->trans('AmountHT') . ' ';
+ print '' . price($object->total_ht, '', $langs, 1, -1, -1, $conf->currency) . ' ';
+ print ' ';
+
+ print '' . $langs->trans("AmountVAT") . ' ' . price($object->total_tva, '', $langs, 1, -1, -1, $conf->currency) . ' ';
+ print ' ';
+
+ // Amount Local Taxes
+ if (($mysoc->localtax1_assuj == "1" && $mysoc->useLocalTax(1)) || $object->total_localtax1 != 0) { // Localtax1
+ print '' . $langs->transcountry("AmountLT1", $mysoc->country_code) . ' ';
+ print '' . price($object->total_localtax1, 1, '', 1, -1, -1, $conf->currency) . ' ';
+ }
+ if (($mysoc->localtax2_assuj == "1" && $mysoc->useLocalTax(2)) || $object->total_localtax2 != 0) { // Localtax2
+ print '' . $langs->transcountry("AmountLT2", $mysoc->country_code) . ' ';
+ print '' . price($object->total_localtax2, 1, '', 1, -1, -1, $conf->currency) . ' ';
+ }
+
+ print '' . $langs->trans("AmountTTC") . ' ' . price($object->total_ttc, '', $langs, 1, -1, -1, $conf->currency) . ' ';
+ print ' ';
+
+ // Payment term
+ print '';
+ print '';
+ print ' ';
+ if ($action == 'editconditions') {
+ $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->cond_reglement_id, 'cond_reglement_id');
+ } else {
+ $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->cond_reglement_id, 'none');
+ }
+
+ print ' ';
+
+ // Payment mode
+ print '';
+ print '';
+ print ' ';
+ if ($action == 'editmode') {
+ $form->form_modes_reglement($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1);
+ } else {
+ $form->form_modes_reglement($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->mode_reglement_id, 'none');
+ }
+ print ' ';
+
+ // Multicurrency
+ if (! empty($conf->multicurrency->enabled)) {
+ // Multicurrency code
+ print '';
+ print '';
+ print '';
+ print ' ';
+ $htmlname = (($usercancreate && $action == 'editmulticurrencycode') ? 'multicurrency_code' : 'none');
+ $form->form_multicurrency_code($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_code, $htmlname);
+ print ' ';
+
+ // Multicurrency rate
+ if ($object->multicurrency_code != $conf->currency || $object->multicurrency_tx != 1) {
+ print '';
+ print '';
+ print '';
+ print ' ';
+ if ($action == 'editmulticurrencyrate' || $action == 'actualizemulticurrencyrate') {
+ if ($action == 'actualizemulticurrencyrate') {
+ list($object->fk_multicurrency, $object->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($object->db, $object->multicurrency_code);
+ }
+ $form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, ($usercancreate ? 'multicurrency_tx' : 'none'), $object->multicurrency_code);
+ } else {
+ $form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, 'none', $object->multicurrency_code);
+ if ($object->statut == $object::STATUS_DRAFT && $object->multicurrency_code && $object->multicurrency_code != $conf->currency) {
+ print '';
+ }
+ }
+ print ' ';
+ }
+ }
+
+ // Help of substitution key
+ $dateexample = dol_now();
+ if (! empty($object->frequency) && ! empty($object->date_when)) {
+ $dateexample = $object->date_when;
+ }
+
+ $substitutionarray = getCommonSubstitutionArray($langs, 2, null, $object);
+
+ $substitutionarray['__INVOICE_PREVIOUS_MONTH__'] = $langs->trans("PreviousMonthOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree($dateexample, -1, 'm'), '%m') . ')';
+ $substitutionarray['__INVOICE_MONTH__'] = $langs->trans("MonthOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date($dateexample, '%m') . ')';
+ $substitutionarray['__INVOICE_NEXT_MONTH__'] = $langs->trans("NextMonthOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree($dateexample, 1, 'm'), '%m') . ')';
+ $substitutionarray['__INVOICE_PREVIOUS_MONTH_TEXT__'] = $langs->trans("TextPreviousMonthOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree($dateexample, -1, 'm'), '%B') . ')';
+ $substitutionarray['__INVOICE_MONTH_TEXT__'] = $langs->trans("TextMonthOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date($dateexample, '%B') . ')';
+ $substitutionarray['__INVOICE_NEXT_MONTH_TEXT__'] = $langs->trans("TextNextMonthOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree($dateexample, 1, 'm'), '%B') . ')';
+ $substitutionarray['__INVOICE_PREVIOUS_YEAR__'] = $langs->trans("PreviousYearOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree($dateexample, -1, 'y'), '%Y') . ')';
+ $substitutionarray['__INVOICE_YEAR__'] = $langs->trans("YearOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date($dateexample, '%Y') . ')';
+ $substitutionarray['__INVOICE_NEXT_YEAR__'] = $langs->trans("NextYearOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree($dateexample, 1, 'y'), '%Y') . ')';
+ // Only on template invoices
+ $substitutionarray['__INVOICE_DATE_NEXT_INVOICE_BEFORE_GEN__'] = $langs->trans("DateNextInvoiceBeforeGen") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(($object->date_when ? $object->date_when : dol_now()), 'dayhour') . ')';
+ $substitutionarray['__INVOICE_DATE_NEXT_INVOICE_AFTER_GEN__'] = $langs->trans("DateNextInvoiceAfterGen") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree(($object->date_when ? $object->date_when : dol_now()), $object->frequency, $object->unit_frequency), 'dayhour') . ')';
+ $substitutionarray['__INVOICE_COUNTER_CURRENT__'] = $object->nb_gen_done;
+ $substitutionarray['__INVOICE_COUNTER_MAX__'] = $object->nb_gen_max;
+
+ $htmltext = '' . $langs->trans("FollowingConstantsWillBeSubstituted") . ': ';
+ foreach ($substitutionarray as $key => $val) {
+ $htmltext .= $key . ' = ' . $langs->trans($val) . ' ';
+ }
+ $htmltext .= ' ';
+
+ // Note public
+ print '';
+ print $form->editfieldkey($form->textwithpicto($langs->trans('NotePublic'), $htmltext, 1, 'help', '', 0, 2, 'notepublic'), 'note_public', $object->note_public, $object, $usercancreate);
+ print ' ';
+ print $form->editfieldval($langs->trans("NotePublic"), 'note_public', $object->note_public, $object, $usercancreate, 'textarea:' . ROWS_4 . ':90%', '', null, null, '', 1);
+ print ' ';
+ print ' ';
+
+ // Note private
+ print '';
+ print $form->editfieldkey($form->textwithpicto($langs->trans("NotePrivate"), $htmltext, 1, 'help', '', 0, 2, 'noteprivate'), 'note_private', $object->note_private, $object, $usercancreate);
+ print ' ';
+ print $form->editfieldval($langs->trans("NotePrivate"), 'note_private', $object->note_private, $object, $usercancreate, 'textarea:' . ROWS_4 . ':90%', '', null, null, '', 1);
+ print ' ';
+ print ' ';
+
+ // Bank Account
+ print '';
+ print '';
+ print ' ';
+ if ($action == 'editbankaccount') {
+ $form->formSelectAccount($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->fk_account, 'fk_account', 1);
+ } else {
+ $form->formSelectAccount($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->fk_account, 'none');
+ }
+ print " ";
+ print ' ';
+
+ // Model pdf
+ print '';
+ print '';
+ print $langs->trans('Model');
+ print ' ';
+ if ($action != 'editmodelpdf' && $usercancreate && $object->statut == FactureFournisseurRec::STATUS_NOTSUSPENDED) {
+ print ' ' . img_edit($langs->trans('SetModel'), 1) . ' ';
+ }
+ print '
';
+ print ' ';
+ if ($action == 'editmodelpdf') {
+ include_once DOL_DOCUMENT_ROOT . '/core/modules/supplier_invoice/modules_facturefournisseur.php';
+ $list = array();
+ $models = ModelePDFSuppliersInvoices::liste_modeles($db);
+ foreach ($models as $k => $model) {
+ $list[] = str_replace(':', '|', $k) . ':' . $model;
+ }
+ $select = 'select;' . implode(',', $list);
+ //TODO : Droits
+ print $form->editfieldval($langs->trans('Model'), 'modelpdf', $object->model_pdf, $object, $usercancreate, $select);
+ } else {
+ print $object->model_pdf;
+ }
+ print " ";
+ print ' ';
+
+ // Other attributes
+ $cols = 2;
+ include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
+
+ print '
';
+
+ print '
';
+ print '
';
+ print '
';
+
+ /*
+ * Recurrence
+ */
+ $title = $langs->trans("Recurrence");
+ //print load_fiche_titre($title, '', 'calendar');
+
+ print '
';
+
+ print '' . img_picto('', 'recurring', 'class="pictofixedwidth"') . $title . ' ';
+
+ // if "frequency" is empty or = 0, the reccurence is disabled
+ print '';
+ print '';
+ print ' ';
+ if ($action == 'editfrequency') {
+ print '';
+ } else {
+ if ($object->frequency > 0) {
+ print $langs->trans('FrequencyPer_' . $object->unit_frequency, $object->frequency);
+ } else {
+ print $langs->trans("NotARecurringInvoiceTemplate");
+ }
+ }
+ print ' ';
+
+ // Date when (next invoice generation)
+ print '';
+ if ($action == 'date_when' || $object->frequency > 0) {
+ print $form->editfieldkey($langs->trans("NextDateToExecution"), 'date_when', $object->date_when, $object, $usercancreate, 'day');
+ } else {
+ print $langs->trans("NextDateToExecution");
+ }
+ print ' ';
+ if ($action == 'date_when' || $object->frequency > 0) {
+ print $form->editfieldval($langs->trans("NextDateToExecution"), 'date_when', $object->date_when, $object, $usercancreate, 'day', $object->date_when, null, '', '', 0, 'strikeIfMaxNbGenReached');
+ }
+ //var_dump(dol_print_date($object->date_when+60, 'dayhour').' - '.dol_print_date($now, 'dayhour'));
+ if (! $object->isMaxNbGenReached()) {
+ if (! $object->suspended && $action != 'editdate_when' && $object->frequency > 0 && $object->date_when && $object->date_when < $now) {
+ print img_warning($langs->trans("Late"));
+ }
+ } else {
+ print img_info($langs->trans("MaxNumberOfGenerationReached"));
+ }
+ print ' ';
+ print ' ';
+
+ // Max period / Rest period
+ print '';
+ if ($action == 'nb_gen_max' || $object->frequency > 0) {
+ print $form->editfieldkey($langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max, $object, $usercancreate);
+ } else {
+ print $langs->trans("MaxPeriodNumber");
+ }
+ print ' ';
+ if ($action == 'nb_gen_max' || $object->frequency > 0) {
+ print $form->editfieldval($langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max ? $object->nb_gen_max : '', $object, $usercancreate);
+ } else {
+ print '';
+ }
+ print ' ';
+ print ' ';
+
+ // Status of generated invoices
+ print '';
+ if ($action == 'auto_validate' || $object->frequency > 0) {
+ print $form->editfieldkey($langs->trans("StatusOfGeneratedInvoices"), 'auto_validate', $object->auto_validate, $object, $usercancreate);
+ } else {
+ print $langs->trans("StatusOfGeneratedInvoices");
+ }
+ print ' ';
+ $select = 'select;0:' . $langs->trans('BillStatusDraft') . ',1:' . $langs->trans('BillStatusValidated');
+ if ($action == 'auto_validate' || $object->frequency > 0) {
+ print $form->editfieldval($langs->trans("StatusOfGeneratedInvoices"), 'auto_validate', $object->auto_validate, $object, $usercancreate, $select);
+ }
+ print ' ';
+ // Auto generate documents
+ if (! empty($conf->global->INVOICE_REC_CAN_DISABLE_DOCUMENT_FILE_GENERATION)) {
+ print '';
+ print '';
+ if ($action == 'generate_pdf' || $object->frequency > 0) {
+ print $form->editfieldkey($langs->trans("StatusOfGeneratedDocuments"), 'generate_pdf', $object->generate_pdf, $object, $usercancreate);
+ } else {
+ print $langs->trans("StatusOfGeneratedDocuments");
+ }
+ print ' ';
+ print '';
+ $select = 'select;0:' . $langs->trans('DoNotGenerateDoc') . ',1:' . $langs->trans('AutogenerateDoc');
+ if ($action == 'generate_pdf' || $object->frequency > 0) {
+ print $form->editfieldval($langs->trans("StatusOfGeneratedDocuments"), 'generate_pdf', $object->generate_pdf, $object, $usercancreate, $select);
+ }
+ print ' ';
+ print ' ';
+ } else {
+ print ' ';
+ }
+
+ print '
';
+
+ // Frequencry/Recurring section
+ if ($object->frequency > 0) {
+ print '
';
+
+ if (empty($conf->cron->enabled)) {
+ print info_admin($langs->trans("EnableAndSetupModuleCron", $langs->transnoentitiesnoconv("Module2300Name")));
+ }
+
+ print '
';
+ print '
';
+
+ // Nb of generation already done
+ print '' . $langs->trans("NbOfGenerationDone") . ' ';
+ print '';
+ print $object->nb_gen_done ? $object->nb_gen_done : '0';
+ print ' ';
+ print ' ';
+
+ // Date last
+ print '';
+ print $langs->trans("DateLastGeneration");
+ print ' ';
+ print dol_print_date($object->date_last_gen, 'dayhour');
+ print ' ';
+ print ' ';
+
+ print '
';
+
+ print '
';
+ }
+
+ print '
';
+ print '
';
+
+ print '
';
+
+ // Lines
+ print ' \n";
+
+ print dol_get_fiche_end();
+
+ /*
+ * Action bar
+ */
+ print '';
+
+ if (empty($object->suspended)) {
+ if ($usercancreate) {
+ if (! empty($object->frequency) && $object->nb_gen_max > 0 && ($object->nb_gen_done >= $object->nb_gen_max)) {
+ print '
';
+ } else {
+ if (empty($object->frequency) || $object->date_when <= $nowlasthour) {
+ print '
';
+ } else {
+ print '
';
+ }
+ }
+ } else {
+ print '
';
+ }
+ }
+
+ if ($usercancreate) {
+ if (empty($object->suspended)) {
+ print '
';
+ } else {
+ print '
';
+ }
+ }
+
+ //if ($object->statut == Facture::STATUS_DRAFT && ($user->rights->fournisseur->facture->supprimer || $user->rights->supplier_invoice->supprimer))
+ if (($user->rights->fournisseur->facture->supprimer || $user->rights->supplier_invoice->supprimer)) {
+ print '
';
+ }
+
+ print '
';
+
+ print '';
+ print '
'; // ancre
+
+ // Show links to link elements
+ $linktoelem = $form->showLinkToObjectBlock($object, null, array('invoice'));
+
+ $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
+
+ print '
';
+ }
+}
+
+// End of page
+llxFooter();
+$db->close();
diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php
index 76159d177c5..4b052981955 100644
--- a/htdocs/fourn/facture/card.php
+++ b/htdocs/fourn/facture/card.php
@@ -37,6 +37,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/modules/supplier_invoice/modules_facturefournisseur.php';
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
+require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture-rec.class.php';
require_once DOL_DOCUMENT_ROOT.'/fourn/class/paiementfourn.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/discount.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/fourn.lib.php';
@@ -544,9 +545,9 @@ if (empty($reshook)) {
if ($line->product_type < 9 && $line->total_ht != 0) { // Remove lines with product_type greater than or equal to 9 and no need to create discount if amount is null
$keyforvatrate = $line->tva_tx.($line->vat_src_code ? ' ('.$line->vat_src_code.')' : '');
- $amount_ht[$line->tva_tx] += $line->total_ht;
- $amount_tva[$line->tva_tx] += $line->total_tva;
- $amount_ttc[$line->tva_tx] += $line->total_ttc;
+ $amount_ht[$keyforvatrate] += $line->total_ht;
+ $amount_tva[$keyforvatrate] += $line->total_tva;
+ $amount_ttc[$keyforvatrate] += $line->total_ttc;
$multicurrency_amount_ht[$keyforvatrate] += $line->multicurrency_total_ht;
$multicurrency_amount_tva[$keyforvatrate] += $line->multicurrency_total_tva;
$multicurrency_amount_ttc[$keyforvatrate] += $line->multicurrency_total_ttc;
@@ -883,8 +884,52 @@ if (empty($reshook)) {
}
}
+ // Standard invoice or Deposit invoice, created from a Predefined template invoice
+ if ((GETPOST('type') == FactureFournisseur::TYPE_STANDARD || GETPOST('type') == FactureFournisseur::TYPE_DEPOSIT) && GETPOST('fac_rec', 'int') > 0) {
+ if (empty($dateinvoice)) {
+ $error++;
+ setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors');
+ $action = 'create';
+ } elseif ($dateinvoice > (dol_get_last_hour(dol_now('tzuserrel')) + (empty($conf->global->INVOICE_MAX_FUTURE_DELAY) ? 0 : $conf->global->INVOICE_MAX_FUTURE_DELAY))) {
+ $error++;
+ setEventMessages($langs->trans("ErrorDateIsInFuture"), null, 'errors');
+ $action = 'create';
+ }
+
+ if (!$error) {
+ $object->socid = GETPOST('socid', 'int');
+ $object->type = GETPOST('type');
+ $object->ref = GETPOST('ref');
+ $object->date = $dateinvoice;
+ $object->note_public = trim(GETPOST('note_public', 'restricthtml'));
+ $object->note_private = trim(GETPOST('note_private', 'restricthtml'));
+ $object->ref_client = GETPOST('ref_client');
+ $object->model_pdf = GETPOST('model');
+ $object->fk_project = GETPOST('projectid', 'int');
+ $object->cond_reglement_id = (GETPOST('type') == 3 ? 1 : GETPOST('cond_reglement_id'));
+ $object->mode_reglement_id = GETPOST('mode_reglement_id', 'int');
+ $object->fk_account = GETPOST('fk_account', 'int');
+ $object->amount = price2num(GETPOST('amount'));
+ $object->remise_absolue = price2num(GETPOST('remise_absolue'), 'MU');
+ $object->remise_percent = price2num(GETPOST('remise_percent'), '', 2);
+ $object->fk_incoterms = GETPOST('incoterm_id', 'int');
+ $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
+ $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha');
+ $object->multicurrency_tx = GETPOST('originmulticurrency_tx', 'int');
+
+ // Source facture
+ $object->fac_rec = GETPOST('fac_rec', 'int');
+ $fac_rec = new FactureFournisseurRec($db);
+ $fac_rec->fetch($object->fac_rec);
+ $fac_rec->fetch_lines();
+ $object->lines = $fac_rec->lines;
+
+ $id = $object->create($user); // This include recopy of links from recurring invoice and recurring invoice lines
+ }
+ }
+
// Standard invoice or Deposit invoice, not from a Predefined template invoice
- if (GETPOST('type') == FactureFournisseur::TYPE_STANDARD || GETPOST('type') == FactureFournisseur::TYPE_DEPOSIT) {
+ if (GETPOST('type') == FactureFournisseur::TYPE_STANDARD || GETPOST('type') == FactureFournisseur::TYPE_DEPOSIT && GETPOST('fac_rec') <= 0) {
if (GETPOST('socid', 'int') < 1) {
setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('Supplier')), null, 'errors');
$action = 'create';
@@ -1336,6 +1381,7 @@ if (empty($reshook)) {
setEventMessages($object->error, $object->errors, 'errors');
}
} elseif ($action == 'addline' && $usercancreate) {
+ // Add a product line
$db->begin();
$ret = $object->fetch($id);
@@ -1368,7 +1414,11 @@ if (empty($reshook)) {
$price_ttc = price2num(GETPOST('price_ttc'), 'MU', 2);
$price_ttc_devise = price2num(GETPOST('multicurrency_price_ttc'), 'CU', 2);
$qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS');
- $remise_percent = price2num(GETPOST('remise_percent'.$predef), 2);
+
+ $remise_percent = (GETPOSTISSET('remise_percent'.$predef) ? price2num(GETPOST('remise_percent'.$predef, 'alpha'), '', 2) : 0);
+ if (empty($remise_percent)) {
+ $remise_percent = 0;
+ }
// Extrafields
$extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
@@ -1957,11 +2007,17 @@ if ($action == 'create') {
// Ref
print ''.$langs->trans('Ref').' '.$langs->trans('Draft').' ';
+ $exampletemplateinvoice = new FactureFournisseurRec($db);
+ $invoice_predefined = new FactureFournisseurRec($db);
+ if (empty($origin) && empty($originid) && GETPOST('fac_rec', 'int') > 0) {
+ $invoice_predefined->fetch(GETPOST('fac_rec', 'int'));
+ }
+
// Third party
print ''.$langs->trans('Supplier').' ';
print '';
- if ($societe->id > 0) {
+ if ($societe->id > 0 && (!GETPOST('fac_rec', 'int') || !empty($invoice_predefined->frequency))) {
$absolute_discount = $societe->getAvailableDiscounts('', '', 0, 1);
print $societe->getNomUrl(1, 'supplier');
print ' ';
@@ -1973,16 +2029,86 @@ if ($action == 'create') {
$(document).ready(function() {
$("#socid").change(function() {
var socid = $(this).val();
- // reload page
- window.location.href = "'.$_SERVER["PHP_SELF"].'?action=create&socid="+socid;
+ var fac_rec = $(\'#fac_rec\').val();
+ window.location.href = "'.$_SERVER["PHP_SELF"].'?action=create&socid="+socid+"&fac_rec="+fac_rec;
});
});
';
}
- print ' ';
+ if (!GETPOST('fac_rec', 'int')) {
+ print ' ';
+ }
}
print ' ';
+ // Overwrite some values if creation of invoice is from a predefined invoice
+ if (empty($origin) && empty($originid) && GETPOST('fac_rec', 'int') > 0) {
+ $invoice_predefined->fetch(GETPOST('fac_rec', 'int'));
+
+ $dateinvoice = $invoice_predefined->date_when; // To use next gen date by default later
+ if (empty($projectid)) {
+ $projectid = $invoice_predefined->fk_project;
+ }
+ $cond_reglement_id = $invoice_predefined->cond_reglement_id;
+ $mode_reglement_id = $invoice_predefined->mode_reglement_id;
+ $fk_account = $invoice_predefined->fk_account;
+ $note_public = $invoice_predefined->note_public;
+ $note_private = $invoice_predefined->note_private;
+
+ if (!empty($invoice_predefined->multicurrency_code)) {
+ $currency_code = $invoice_predefined->multicurrency_code;
+ }
+ if (!empty($invoice_predefined->multicurrency_tx)) {
+ $currency_tx = $invoice_predefined->multicurrency_tx;
+ }
+
+ $sql = 'SELECT r.rowid, r.titre as title, r.total_ttc';
+ $sql .= ' FROM '.MAIN_DB_PREFIX.'facture_fourn_rec as r';
+ $sql .= ' WHERE r.fk_soc = '. (int) $invoice_predefined->socid;
+
+ $resql = $db->query($sql);
+ if ($resql) {
+ $num = $db->num_rows($resql);
+ $i = 0;
+
+ if ($num > 0) {
+ print ''.$langs->trans('CreateFromRepeatableInvoice').' ';
+ //print ' ';
+ print ''; // We may want to change the template to use
+ print ' ';
+ while ($i < $num) {
+ $objp = $db->fetch_object($resql);
+ print 'rowid) {
+ print ' selected';
+ $exampletemplateinvoice->fetch(GETPOST('fac_rec', 'int'));
+ }
+ print '>'.$objp->title.' ('.price($objp->total_ttc).' '.$langs->trans("TTC").') ';
+ $i++;
+ }
+ print ' ';
+ // Option to reload page to retrieve customer informations. Note, this clear other input
+ if (empty($conf->global->RELOAD_PAGE_ON_TEMPLATE_CHANGE_DISABLED)) {
+ print '';
+ }
+ print ' ';
+ }
+ $db->free($resql);
+ } else {
+ dol_print_error($db);
+ }
+ }
+
// Ref supplier
print ''.$langs->trans('RefSupplier').' id > 0) {
@@ -2288,6 +2414,34 @@ if ($action == 'create') {
print ' ';
}
+ // Help of substitution key
+ $htmltext = '';
+ if (GETPOST('fac_rec', 'int') > 0) {
+ $dateexample = $newdateinvoice ? $newdateinvoice : $dateinvoice;
+ if (empty($dateexample)) {
+ $dateexample = dol_now();
+ }
+ $substitutionarray = array(
+ '__TOTAL_HT__' => $langs->trans("AmountHT").' ('.$langs->trans("Example").': '.price($exampletemplateinvoice->total_ht).')',
+ '__TOTAL_TTC__' => $langs->trans("AmountTTC").' ('.$langs->trans("Example").': '.price($exampletemplateinvoice->total_ttc).')',
+ '__INVOICE_PREVIOUS_MONTH__' => $langs->trans("PreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'm'), '%m').')',
+ '__INVOICE_MONTH__' => $langs->trans("MonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample, '%m').')',
+ '__INVOICE_NEXT_MONTH__' => $langs->trans("NextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'm'), '%m').')',
+ '__INVOICE_PREVIOUS_MONTH_TEXT__' => $langs->trans("TextPreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'm'), '%B').')',
+ '__INVOICE_MONTH_TEXT__' => $langs->trans("TextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample, '%B').')',
+ '__INVOICE_NEXT_MONTH_TEXT__' => $langs->trans("TextNextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'm'), '%B').')',
+ '__INVOICE_PREVIOUS_YEAR__' => $langs->trans("PreviousYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'y'), '%Y').')',
+ '__INVOICE_YEAR__' => $langs->trans("YearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample, '%Y').')',
+ '__INVOICE_NEXT_YEAR__' => $langs->trans("NextYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'y'), '%Y').')'
+ );
+
+ $htmltext = ''.$langs->trans("FollowingConstantsWillBeSubstituted").': ';
+ foreach ($substitutionarray as $key => $val) {
+ $htmltext .= $key.' = '.$langs->trans($val).' ';
+ }
+ $htmltext .= ' ';
+ }
+
// Intracomm report
if (!empty($conf->intracommreport->enabled)) {
$langs->loadLangs(array("intracommreport"));
@@ -2776,6 +2930,19 @@ if ($action == 'create') {
print ' ';
}
}
+
+ if ($object->fk_fac_rec_source > 0) {
+ $tmptemplate = new FactureFournisseurRec($db);
+ $result = $tmptemplate->fetch($object->fk_fac_rec_source);
+ if ($result > 0) {
+ print ' ';
+ $link = ''.dol_escape_htmltag($tmptemplate->titre).' ';
+ $s = $langs->transnoentities("GeneratedFromSupplierTemplate", $link);
+
+ print $s;
+ print ' ';
+ }
+ }
print '';
@@ -3559,6 +3726,13 @@ if ($action == 'create') {
print 'id.'&action=clone&socid='.$object->socid.'">'.$langs->trans('ToClone').' ';
}
+ // Clone as predefined / Create template
+ if (($object->type == FactureFournisseur::TYPE_STANDARD || $object->type == FactureFournisseur::TYPE_DEPOSIT) && $object->statut == 0 && $usercancreate) {
+ if (!$objectidnext && count($object->lines) > 0) {
+ print ''.$langs->trans("ChangeIntoRepeatableInvoice").' ';
+ }
+ }
+
// Delete
$isErasable = $object->is_erasable();
if ($action != 'confirm_edit' && ($user->rights->fournisseur->facture->supprimer || ($usercancreate && $isErasable == 1))) { // isErasable = 1 means draft with temporary ref (draft can always be deleted with no need of permissions)
diff --git a/htdocs/fourn/facture/list-rec.php b/htdocs/fourn/facture/list-rec.php
new file mode 100644
index 00000000000..7da3a224d4f
--- /dev/null
+++ b/htdocs/fourn/facture/list-rec.php
@@ -0,0 +1,922 @@
+
+ * Copyright (C) 2004-2016 Laurent Destailleur
+ * Copyright (C) 2005-2012 Regis Houssin
+ * Copyright (C) 2013 Florian Henry
+ * Copyright (C) 2013 Juanjo Menent
+ * Copyright (C) 2015 Jean-François Ferry
+ * Copyright (C) 2012 Cedric Salvador
+ * Copyright (C) 2015-2021 Alexandre Spangaro
+ * Copyright (C) 2016 Meziane Sof
+ *
+ * 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 .
+ */
+
+/**
+ * \file htdocs/compta/facture/invoicetemplate_list.php
+ * \ingroup facture
+ * \brief Page to show list of template/recurring invoices
+ */
+
+require '../../main.inc.php';
+require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture-rec.class.php';
+require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
+require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/invoice.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
+
+// Load translation files required by the page
+$langs->loadLangs(array('bills', 'compta', 'admin', 'other', 'suppliers'));
+
+$action = GETPOST('action', 'alpha');
+$massaction = GETPOST('massaction', 'alpha');
+$show_files = GETPOST('show_files', 'int');
+$confirm = GETPOST('confirm', 'alpha');
+$cancel = GETPOST('cancel', 'alpha');
+$toselect = GETPOST('toselect', 'array');
+$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'invoicetemplatelist'; // To manage different context of search
+$optioncss = GETPOST('optioncss', 'alpha');
+
+$socid = GETPOST('socid', 'int');
+
+// Security check
+$id = (GETPOST('facid', 'int') ?GETPOST('facid', 'int') : GETPOST('id', 'int'));
+$lineid = GETPOST('lineid', 'int');
+$ref = GETPOST('ref', 'alpha');
+if ($user->socid) {
+ $socid = $user->socid;
+}
+$objecttype = 'facture_fourn_rec';
+if ($action == "create" || $action == "add") {
+ $objecttype = '';
+}
+$result = restrictedArea($user, 'facture', $id, $objecttype);
+
+$search_ref = GETPOST('search_ref');
+$search_societe = GETPOST('search_societe');
+$search_montant_ht = GETPOST('search_montant_ht');
+$search_montant_vat = GETPOST('search_montant_vat');
+$search_montant_ttc = GETPOST('search_montant_ttc');
+$search_payment_mode = GETPOST('search_payment_mode');
+$search_payment_term = GETPOST('search_payment_term');
+$search_date_startday = GETPOST('search_date_startday', 'int');
+$search_date_startmonth = GETPOST('search_date_startmonth', 'int');
+$search_date_startyear = GETPOST('search_date_startyear', 'int');
+$search_date_endday = GETPOST('search_date_endday', 'int');
+$search_date_endmonth = GETPOST('search_date_endmonth', 'int');
+$search_date_endyear = GETPOST('search_date_endyear', 'int');
+$search_date_start = dol_mktime(0, 0, 0, $search_date_startmonth, $search_date_startday, $search_date_startyear); // Use tzserver
+$search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_endday, $search_date_endyear);
+$search_date_when_startday = GETPOST('search_date_when_startday', 'int');
+$search_date_when_startmonth = GETPOST('search_date_when_startmonth', 'int');
+$search_date_when_startyear = GETPOST('search_date_when_startyear', 'int');
+$search_date_when_endday = GETPOST('search_date_when_endday', 'int');
+$search_date_when_endmonth = GETPOST('search_date_when_endmonth', 'int');
+$search_date_when_endyear = GETPOST('search_date_when_endyear', 'int');
+$search_date_when_start = dol_mktime(0, 0, 0, $search_date_when_startmonth, $search_date_when_startday, $search_date_when_startyear); // Use tzserver
+$search_date_when_end = dol_mktime(23, 59, 59, $search_date_when_endmonth, $search_date_when_endday, $search_date_when_endyear);
+$search_recurring = GETPOST('search_recurring', 'int');
+$search_frequency = GETPOST('search_frequency', 'alpha');
+$search_unit_frequency = GETPOST('search_unit_frequency', 'alpha');
+$search_status = GETPOST('search_status', 'int');
+
+$limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
+$sortfield = GETPOST('sortfield', 'alpha');
+$sortorder = GETPOST('sortorder', 'alpha');
+$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST('page', 'int');
+if (empty($page) || $page == -1) {
+ $page = 0;
+} // If $page is not defined, or '' or -1
+$offset = $limit * $page;
+if (!$sortorder) {
+ $sortorder = 'DESC';
+}
+if (!$sortfield) {
+ $sortfield = 'f.titre';
+}
+$pageprev = $page - 1;
+$pagenext = $page + 1;
+
+$object = new FactureFournisseurRec($db);
+if (($id > 0 || $ref) && $action != 'create' && $action != 'add') {
+ $ret = $object->fetch($id, $ref);
+ if (!$ret) {
+ setEventMessages($langs->trans("ErrorRecordNotFound"), null, 'errors');
+ }
+}
+
+// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
+$hookmanager->initHooks(array('supplierinvoicereclist'));
+$extrafields = new ExtraFields($db);
+
+// fetch optionals attributes and labels
+$extrafields->fetch_name_optionals_label($object->table_element);
+
+$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
+
+$permissionnote = $user->rights->facture->creer; // Used by the include of actions_setnotes.inc.php
+$permissiondellink = $user->rights->facture->creer; // Used by the include of actions_dellink.inc.php
+$permissiontoedit = $user->rights->facture->creer; // Used by the include of actions_lineupdonw.inc.php
+
+$arrayfields = array(
+ 'f.titre'=>array('label'=>'Ref', 'checked'=>1),
+ 's.nom'=>array('label'=>'ThirdParty', 'checked'=>1),
+ 'f.total_ht'=>array('label'=>'AmountHT', 'checked'=>1),
+ 'f.total_tva'=>array('label'=>'AmountVAT', 'checked'=>1),
+ 'f.total_ttc'=>array('label'=>'AmountTTC', 'checked'=>1),
+ 'f.fk_mode_reglement'=>array('label'=>'PaymentMode', 'checked'=>0),
+ 'f.fk_cond_reglement'=>array('label'=>'PaymentTerm', 'checked'=>0),
+ 'recurring'=>array('label'=>'RecurringInvoice', 'checked'=>1),
+ 'f.frequency'=>array('label'=>'Frequency', 'checked'=>1),
+ 'f.unit_frequency'=>array('label'=>'FrequencyUnit', 'checked'=>1),
+ 'f.nb_gen_done'=>array('label'=>'NbOfGenerationDoneShort', 'checked'=>1),
+ 'f.date_last_gen'=>array('label'=>'DateLastGenerationShort', 'checked'=>1),
+ 'f.date_when'=>array('label'=>'NextDateToExecutionShort', 'checked'=>1),
+ 'f.fk_user_author'=>array('label'=>'UserCreation', 'checked'=>0, 'position'=>500),
+ 'f.fk_user_modif'=>array('label'=>'UserModification', 'checked'=>0, 'position'=>505),
+ 'f.datec'=>array('label'=>'DateCreation', 'checked'=>0, 'position'=>520),
+ 'f.tms'=>array('label'=>'DateModificationShort', 'checked'=>0, 'position'=>525),
+ 'suspended '=>array('label'=>'Status', 'checked'=>1, 'position'=>1000),
+);
+// Extra fields
+include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php';
+
+$object->fields = dol_sort_array($object->fields, 'position');
+$arrayfields = dol_sort_array($arrayfields, 'position');
+
+if ($socid > 0) {
+ $tmpthirdparty = new Societe($db);
+ $res = $tmpthirdparty->fetch($socid);
+ if ($res > 0) {
+ $search_societe = $tmpthirdparty->name;
+ }
+}
+$objecttype = 'facture_fourn_rec';
+
+$result = restrictedArea($user, 'facture', $object->id, $objecttype);
+
+
+/*
+ * Actions
+ */
+
+if (GETPOST('cancel', 'alpha')) {
+ $action = 'list';
+ $massaction = '';
+}
+if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
+ $massaction = '';
+}
+
+$parameters = array('socid' => $socid);
+$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
+if ($reshook < 0) {
+ setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
+}
+
+if (empty($reshook)) {
+ if (GETPOST('cancel', 'alpha')) {
+ $action = '';
+ }
+
+ // Selection of new fields
+ include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
+
+ // Do we click on purge search criteria ?
+ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All test are required to be compatible with all browsers
+ $search_ref = '';
+ $search_societe = '';
+ $search_montant_ht = '';
+ $search_montant_vat = '';
+ $search_montant_ttc = '';
+ $search_payment_mode = '';
+ $search_payment_term = '';
+ $search_date_startday = '';
+ $search_date_startmonth = '';
+ $search_date_startyear = '';
+ $search_date_endday = '';
+ $search_date_endmonth = '';
+ $search_date_endyear = '';
+ $search_date_start = '';
+ $search_date_end = '';
+ $search_date_when_startday = '';
+ $search_date_when_startmonth = '';
+ $search_date_when_startyear = '';
+ $search_date_when_endday = '';
+ $search_date_when_endmonth = '';
+ $search_date_when_endyear = '';
+ $search_date_when_start = '';
+ $search_date_when_end = '';
+ $search_recurring = '';
+ $search_frequency = '';
+ $search_unit_frequency = '';
+ $search_status = '';
+ $search_array_options = array();
+ }
+
+ // Mass actions
+ /*$objectclass='MyObject';
+ $objectlabel='MyObject';
+ $permissiontoread = $user->rights->mymodule->read;
+ $permissiontodelete = $user->rights->mymodule->delete;
+ $uploaddir = $conf->mymodule->dir_output;
+ include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';*/
+}
+
+
+/*
+ * View
+ */
+
+$help_url = '';
+llxHeader('', $langs->trans("RepeatableSupplierInvoices"), $help_url);
+
+$form = new Form($db);
+$formother = new FormOther($db);
+if (!empty($conf->projet->enabled)) {
+ $formproject = new FormProjets($db);
+}
+$companystatic = new Societe($db);
+$supplierinvoicerectmp = new FactureFournisseurRec($db);
+$tmpuser = new User($db);
+
+$now = dol_now();
+$tmparray = dol_getdate($now);
+$today = dol_mktime(23, 59, 59, $tmparray['mon'], $tmparray['mday'], $tmparray['year']); // Today is last second of current day
+
+
+/*
+ * List mode
+ */
+
+$sql = "SELECT s.nom as name, s.rowid as socid, f.rowid as facid, f.titre as title, f.total_ht, f.total_tva, f.total_ttc, f.frequency, f.unit_frequency,";
+$sql .= " f.nb_gen_done, f.nb_gen_max, f.date_last_gen, f.date_when, f.suspended,";
+$sql .= " f.datec, f.fk_user_author, f.tms, f.fk_user_modif,";
+$sql .= " f.fk_cond_reglement, f.fk_mode_reglement";
+// Add fields from extrafields
+if (!empty($extrafields->attributes[$object->table_element]['label'])) {
+ foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
+ $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : '');
+ }
+}
+// Add fields from hooks
+$parameters = array();
+$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook
+$sql .= preg_replace('/^,/', '', $hookmanager->resPrint);
+$sql = preg_replace('/,\s*$/', '', $sql);
+
+$sql .= ' FROM '.MAIN_DB_PREFIX.'societe as s, '.MAIN_DB_PREFIX.'facture_fourn_rec as f';
+$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'facture_fourn_rec_extrafields as ef ON ef.fk_object = f.rowid';
+if (empty($user->rights->societe->client->voir) && !$socid) {
+ $sql .= ', '.MAIN_DB_PREFIX.'societe_commerciaux as sc';
+}
+$sql .= ' WHERE f.fk_soc = s.rowid';
+$sql .= ' AND f.entity IN ('.getEntity('invoice').')';
+if (empty($user->rights->societe->client->voir) && !$socid) {
+ $sql .= ' AND s.rowid = sc.fk_soc AND sc.fk_user = '. (int) $user->id;
+}
+if ($search_ref) {
+ $sql .= natural_search('f.titre', $search_ref);
+}
+if ($socid) {
+ $sql .= ' AND s.rowid = '.(int) $socid;
+}
+if ($search_societe) {
+ $sql .= natural_search('s.nom', $search_societe);
+}
+if ($search_montant_ht != '') {
+ $sql .= natural_search('f.total_ht', $search_montant_ht, 1);
+}
+if ($search_montant_vat != '') {
+ $sql .= natural_search('f.total_tva', $search_montant_vat, 1);
+}
+if ($search_montant_ttc != '') {
+ $sql .= natural_search('f.total_ttc', $search_montant_ttc, 1);
+}
+if (!empty($search_payment_mode) && $search_payment_mode != '-1') {
+ $sql .= natural_search('f.fk_mode_reglement', $search_payment_mode, 1);
+}
+if (!empty($search_payment_term) && $search_payment_term != '-1') {
+ $sql .= natural_search('f.fk_cond_reglement', $search_payment_term, 1);
+}
+if ($search_recurring == '1') {
+ $sql .= ' AND f.frequency > 0';
+}
+if ($search_recurring == '0') {
+ $sql .= ' AND (f.frequency IS NULL or f.frequency = 0)';
+}
+if ($search_frequency != '') {
+ $sql .= natural_search('f.frequency', $search_frequency, 1);
+}
+if ($search_unit_frequency != '') {
+ $sql .= ' AND f.frequency > 0'.natural_search('f.unit_frequency', $search_unit_frequency);
+}
+if ($search_status != '' && $search_status >= -1) {
+ if ($search_status == 0) {
+ $sql .= ' AND frequency = 0 AND suspended = 0';
+ }
+ if ($search_status == 1) {
+ $sql .= ' AND frequency != 0 AND suspended = 0';
+ }
+ if ($search_status == -1) {
+ $sql .= ' AND suspended = 1';
+ }
+}
+if ($search_date_start) {
+ $sql .= " AND f.date_last_gen >= '".$db->idate($search_date_start)."'";
+}
+if ($search_date_end) {
+ $sql .= " AND f.date_last_gen <= '".$db->idate($search_date_end)."'";
+}
+if ($search_date_when_start) {
+ $sql .= " AND f.date_when >= '".$db->idate($search_date_when_start)."'";
+}
+if ($search_date_when_end) {
+ $sql .= " AND f.date_when <= '".$db->idate($search_date_when_end)."'";
+}
+
+$tmpsortfield = $sortfield;
+if ($tmpsortfield == 'recurring') {
+ $tmpsortfield = 'f.frequency';
+}
+$sql .= $db->order($tmpsortfield, $sortorder);
+
+$nbtotalofrecords = '';
+if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
+ $result = $db->query($sql);
+ $nbtotalofrecords = $db->num_rows($result);
+ if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0
+ $page = 0;
+ $offset = 0;
+ }
+}
+
+$sql .= $db->plimit($limit + 1, $offset);
+
+$resql = $db->query($sql);
+if ($resql) {
+ $num = $db->num_rows($resql);
+
+ $param = '';
+ if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
+ $param .= '&contextpage='.urlencode($contextpage);
+ }
+ if ($limit > 0 && $limit != $conf->liste_limit) {
+ $param .= '&limit='.urlencode($limit);
+ }
+ if ($socid > 0) {
+ $param .= '&socid='.urlencode($socid);
+ }
+ if ($search_date_startday) {
+ $param .= '&search_date_startday='.urlencode($search_date_startday);
+ }
+ if ($search_date_startmonth) {
+ $param .= '&search_date_startmonth='.urlencode($search_date_startmonth);
+ }
+ if ($search_date_startyear) {
+ $param .= '&search_date_startyear='.urlencode($search_date_startyear);
+ }
+ if ($search_date_endday) {
+ $param .= '&search_date_endday='.urlencode($search_date_endday);
+ }
+ if ($search_date_endmonth) {
+ $param .= '&search_date_endmonth='.urlencode($search_date_endmonth);
+ }
+ if ($search_date_endyear) {
+ $param .= '&search_date_endyear='.urlencode($search_date_endyear);
+ }
+ if ($search_date_when_startday) {
+ $param .= '&search_date_when_startday='.urlencode($search_date_when_startday);
+ }
+ if ($search_date_when_startmonth) {
+ $param .= '&search_date_when_startmonth='.urlencode($search_date_when_startmonth);
+ }
+ if ($search_date_when_startyear) {
+ $param .= '&search_date_when_startyear='.urlencode($search_date_when_startyear);
+ }
+ if ($search_date_when_endday) {
+ $param .= '&search_date_when_endday='.urlencode($search_date_when_endday);
+ }
+ if ($search_date_when_endmonth) {
+ $param .= '&search_date_when_endmonth='.urlencode($search_date_when_endmonth);
+ }
+ if ($search_date_when_endyear) {
+ $param .= '&search_date_when_endyear='.urlencode($search_date_when_endyear);
+ }
+ if ($search_ref) {
+ $param .= '&search_ref='.urlencode($search_ref);
+ }
+ if ($search_societe) {
+ $param .= '&search_societe='.urlencode($search_societe);
+ }
+ if ($search_montant_ht != '') {
+ $param .= '&search_montant_ht='.urlencode($search_montant_ht);
+ }
+ if ($search_montant_vat != '') {
+ $param .= '&search_montant_vat='.urlencode($search_montant_vat);
+ }
+ if ($search_montant_ttc != '') {
+ $param .= '&search_montant_ttc='.urlencode($search_montant_ttc);
+ }
+ if ($search_payment_mode != '') {
+ $param .= '&search_payment_mode='.urlencode($search_payment_mode);
+ }
+ if ($search_payment_term != '') {
+ $param .= '&search_payment_term='.urlencode($search_payment_term);
+ }
+ if ($search_recurring != '' && $search_recurring != '-1') {
+ $param .= '&search_recurring='.urlencode($search_recurring);
+ }
+ if ($search_frequency > 0) {
+ $param .= '&search_frequency='.urlencode($search_frequency);
+ }
+ if ($search_unit_frequency != '') {
+ $param .= '&search_unit_frequency='.urlencode($search_unit_frequency);
+ }
+ if ($search_status != '') {
+ $param .= '&search_status='.urlencode($search_status);
+ }
+ if ($optioncss != '') {
+ $param .= '&optioncss='.urlencode($optioncss);
+ }
+ // Add $param from extra fields
+ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
+
+ $massactionbutton = $form->selectMassAction('', $massaction == 'presend' ? array() : array('presend'=>$langs->trans("SendByMail"), 'builddoc'=>$langs->trans("PDFMerge")));
+
+ $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
+ $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields
+ //$selectedfields.=$form->showCheckAddButtons('checkforselect', 1);
+
+ print '";
+
+ $db->free($resql);
+} else {
+ dol_print_error($db);
+}
+
+// End of page
+llxFooter();
+$db->close();
diff --git a/htdocs/fourn/facture/paiement.php b/htdocs/fourn/facture/paiement.php
index d65b3010367..6dc609041c8 100644
--- a/htdocs/fourn/facture/paiement.php
+++ b/htdocs/fourn/facture/paiement.php
@@ -47,6 +47,9 @@ $langs->loadLangs(array('companies', 'bills', 'banks', 'compta'));
$action = GETPOST('action', 'alpha');
$confirm = GETPOST('confirm', 'alpha');
$optioncss = GETPOST('optioncss', 'alpha');
+$cancel = GETPOST('cancel', 'alpha');
+$backtopage = GETPOST('backtopage', 'alpha');
+$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha');
$facid = GETPOST('facid', 'int');
$socid = GETPOST('socid', 'int');
@@ -110,6 +113,18 @@ $arrayfields = array();
* Actions
*/
+if ($cancel) {
+ if (!empty($backtopageforcancel)) {
+ header("Location: ".$backtopageforcancel);
+ exit;
+ } elseif (!empty($backtopage)) {
+ header("Location: ".$backtopage);
+ exit;
+ }
+ header("Location: ".DOL_URL_ROOT.'/fourn/facture/list.php');
+ exit;
+}
+
if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
$search_ref = "";
$search_account = "";
@@ -776,11 +791,11 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie
// Save + Cancel Buttons
if ($action != 'add_paiement') {
- print ' ';
+ print '';
+ print ' '.$langs->trans("ClosePaidInvoicesAutomatically").' ';
+ print ' ';
+ print ' ';
+ print '
';
}
// Form to confirm payment
diff --git a/htdocs/holiday/class/holiday.class.php b/htdocs/holiday/class/holiday.class.php
index 29e7c41bb5f..d0bed943429 100644
--- a/htdocs/holiday/class/holiday.class.php
+++ b/htdocs/holiday/class/holiday.class.php
@@ -1270,7 +1270,7 @@ class Holiday extends CommonObject
*/
public function getNomUrl($withpicto = 0, $save_lastsearch_value = -1, $notooltip = 0)
{
- global $langs;
+ global $langs, $hookmanager;
$result = '';
@@ -1305,7 +1305,15 @@ class Holiday extends CommonObject
$result .= $this->ref;
}
$result .= $linkend;
-
+ global $action;
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) {
+ $result = $hookmanager->resPrint;
+ } else {
+ $result .= $hookmanager->resPrint;
+ }
return $result;
}
diff --git a/htdocs/hrm/class/establishment.class.php b/htdocs/hrm/class/establishment.class.php
index 88e93f1398f..2a2c4e4b3dd 100644
--- a/htdocs/hrm/class/establishment.class.php
+++ b/htdocs/hrm/class/establishment.class.php
@@ -506,7 +506,7 @@ class Establishment extends CommonObject
global $action, $hookmanager;
$hookmanager->initHooks(array('establishmentdao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
diff --git a/htdocs/hrm/class/evaluation.class.php b/htdocs/hrm/class/evaluation.class.php
index 58ac7fe3324..5e8124fe09a 100644
--- a/htdocs/hrm/class/evaluation.class.php
+++ b/htdocs/hrm/class/evaluation.class.php
@@ -808,7 +808,7 @@ class Evaluation extends CommonObject
global $action, $hookmanager;
$hookmanager->initHooks(array('evaluationdao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
diff --git a/htdocs/hrm/class/evaluationdet.class.php b/htdocs/hrm/class/evaluationdet.class.php
index 115571bb6ba..0ca56d84e60 100644
--- a/htdocs/hrm/class/evaluationdet.class.php
+++ b/htdocs/hrm/class/evaluationdet.class.php
@@ -780,7 +780,7 @@ class Evaluationline extends CommonObject
global $action, $hookmanager;
$hookmanager->initHooks(array('evaluationlinedao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
diff --git a/htdocs/hrm/class/job.class.php b/htdocs/hrm/class/job.class.php
index fc94f4ba6ae..c7f2e1a5f6b 100644
--- a/htdocs/hrm/class/job.class.php
+++ b/htdocs/hrm/class/job.class.php
@@ -814,7 +814,7 @@ class Job extends CommonObject
global $action, $hookmanager;
$hookmanager->initHooks(array('jobdao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
diff --git a/htdocs/hrm/class/position.class.php b/htdocs/hrm/class/position.class.php
index 2401791bb5f..8c51d667f9e 100644
--- a/htdocs/hrm/class/position.class.php
+++ b/htdocs/hrm/class/position.class.php
@@ -788,7 +788,7 @@ class Position extends CommonObject
global $action, $hookmanager;
$hookmanager->initHooks(array('positiondao'));
- $parameters = array('id' => $this->id, 'getnomurl' => $result);
+ $parameters = array('id' => $this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
diff --git a/htdocs/hrm/class/skill.class.php b/htdocs/hrm/class/skill.class.php
index d20d34cfd5e..448538c39a8 100644
--- a/htdocs/hrm/class/skill.class.php
+++ b/htdocs/hrm/class/skill.class.php
@@ -854,7 +854,7 @@ class Skill extends CommonObject
global $action, $hookmanager;
$hookmanager->initHooks(array('jobdao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
diff --git a/htdocs/hrm/class/skilldet.class.php b/htdocs/hrm/class/skilldet.class.php
index 0e0ce87382f..5e2da1ba7aa 100644
--- a/htdocs/hrm/class/skilldet.class.php
+++ b/htdocs/hrm/class/skilldet.class.php
@@ -768,7 +768,7 @@ class Skilldet extends CommonObject
global $action, $hookmanager;
$hookmanager->initHooks(array('skilldetdao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
diff --git a/htdocs/hrm/class/skillrank.class.php b/htdocs/hrm/class/skillrank.class.php
index 587fc889e0f..eb93208040b 100644
--- a/htdocs/hrm/class/skillrank.class.php
+++ b/htdocs/hrm/class/skillrank.class.php
@@ -807,7 +807,7 @@ class SkillRank extends CommonObject
global $action, $hookmanager;
$hookmanager->initHooks(array('skillrankdao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
diff --git a/htdocs/hrm/job_agenda.php b/htdocs/hrm/job_agenda.php
index 6bfafcc1269..0d966e67416 100644
--- a/htdocs/hrm/job_agenda.php
+++ b/htdocs/hrm/job_agenda.php
@@ -189,18 +189,13 @@ if ($object->id > 0) {
}
- print '';
-
if (!empty($conf->agenda->enabled)) {
if (!empty($user->rights->agenda->myactions->create) || !empty($user->rights->agenda->allactions->create)) {
- print '
'.$langs->trans("AddAction").' ';
- } else {
- print '
'.$langs->trans("AddAction").' ';
+ $newcardbutton = '';
+ $newcardbutton .= dolGetButtonTitle($langs->trans('AddAction'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/comm/action/card.php?action=create'.$out);
}
}
- print '
';
-
if (!empty($conf->agenda->enabled) && (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read))) {
$param = '&id='.$object->id.'&socid='.$socid;
if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
@@ -211,7 +206,7 @@ if ($object->id > 0) {
}
- //print load_fiche_titre($langs->trans("ActionsOnJob"), '', '');
+ print load_fiche_titre($langs->trans("ActionsOnJob"), $newcardbutton, '');
// List of all actions
$filters = array();
diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/index.html b/htdocs/includes/restler/framework/Luracast/Restler/explorer/index.html
index 7fedb694c17..5b7ca132af3 100644
--- a/htdocs/includes/restler/framework/Luracast/Restler/explorer/index.html
+++ b/htdocs/includes/restler/framework/Luracast/Restler/explorer/index.html
@@ -68,7 +68,7 @@
if(window.SwaggerTranslator) {
window.SwaggerTranslator.translate();
}
-
+
addApiKeyAuthorization();
},
onFailure: function(data) {
@@ -83,7 +83,9 @@
showRequestHeaders: false,
showOperationIds: false,
displayOperationIds: false,
- displayRequestDuration: true
+ displayRequestDuration: true,
+ /* @CHANGE LDR Add validatorUrl */
+ validatorUrl: null
});
function addApiKeyAuthorization(){
diff --git a/htdocs/install/mysql/data/llx_20_c_departements.sql b/htdocs/install/mysql/data/llx_20_c_departements.sql
index 4fc9ec26366..47f51f33986 100644
--- a/htdocs/install/mysql/data/llx_20_c_departements.sql
+++ b/htdocs/install/mysql/data/llx_20_c_departements.sql
@@ -586,7 +586,7 @@ insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc
insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom) values (307, 'LT', NULL, NULL, NULL, 'LATINA');
insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom) values (313, 'LE', NULL, NULL, NULL, 'LECCE');
insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom) values (309, 'LC', NULL, NULL, NULL, 'LECCO');
-insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom) values (314, 'LI', NULL, NULL, NULL, 'LIVORNO');
+insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom) values (316, 'LI', NULL, NULL, NULL, 'LIVORNO');
insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom) values (309, 'LO', NULL, NULL, NULL, 'LODI');
insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom) values (316, 'LU', NULL, NULL, NULL, 'LUCCA');
insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom) values (310, 'MC', NULL, NULL, NULL, 'MACERATA');
diff --git a/htdocs/install/mysql/data/llx_c_forme_juridique.sql b/htdocs/install/mysql/data/llx_c_forme_juridique.sql
index 7af5d28df8c..a1293084a52 100644
--- a/htdocs/install/mysql/data/llx_c_forme_juridique.sql
+++ b/htdocs/install/mysql/data/llx_c_forme_juridique.sql
@@ -302,12 +302,25 @@ INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (152,
INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (152, '15210', 'Mauritius Trusts', 1);
-- Mexique
-INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15401', 'Sociedad en nombre colectivo', 1);
-INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15402', 'Sociedad en comandita simple', 1);
-INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15403', 'Sociedad de responsabilidad limitada', 1);
-INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15404', 'Sociedad anónima', 1);
-INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15405', 'Sociedad en comandita por acciones', 1);
-INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15406', 'Sociedad cooperativa', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15401', '601 - General de Ley Personas Morales', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15402', '603 - Personas Morales con Fines no Lucrativos', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15403', '605 - Sueldos y Salarios e Ingresos Asimilados a Salarios', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15404', '606 - Arrendamiento', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15405', '607 - Régimen de Enajenación o Adquisición de Bienes', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15406', '608 - Demás ingresos', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15407', '610 - Residentes en el Extranjero sin Establecimiento Permanente en México', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15408', '611 - Ingresos por Dividendos (socios y accionistas)', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15409', '612 - Personas Físicas con Actividades Empresariales y Profesionales', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15410', '614 - Ingresos por intereses', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15411', '615 - Régimen de los ingresos por obtención de premios', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15412', '616 - Sin obligaciones fiscales', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15413', '620 - Sociedades Cooperativas de Producción que optan por diferir sus ingresos', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15414', '621 - Incorporación Fiscal', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15415', '622 - Actividades Agrícolas, Ganaderas, Silvícolas y Pesqueras', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15416', '623 - Opcional para Grupos de Sociedades', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15417', '624 - Coordinados', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15418', '625 - Régimen de las Actividades Empresariales con ingresos a través de Plataformas Tecnológicas', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15419', '626 - Régimen Simplificado de Confianza', 1);
-- Luxembourg
INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (140, '14001', 'Entreprise individuelle', 1);
diff --git a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql
index ab7ea0219ec..6d2d0ae3033 100644
--- a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql
+++ b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql
@@ -649,3 +649,5 @@ ALTER TABLE llx_facture_fourn CHANGE COLUMN fk_mode_transport fk_transport_mode
ALTER TABLE llx_c_socialnetworks DROP INDEX idx_c_socialnetworks_code;
ALTER TABLE llx_c_socialnetworks ADD UNIQUE INDEX idx_c_socialnetworks_code_entity (code, entity);
+
+ALTER TABLE llx_propaldet ADD COLUMN import_key varchar(14);
diff --git a/htdocs/install/mysql/migration/14.0.0-15.0.0.sql b/htdocs/install/mysql/migration/14.0.0-15.0.0.sql
index e68f0497a88..b57d995c251 100644
--- a/htdocs/install/mysql/migration/14.0.0-15.0.0.sql
+++ b/htdocs/install/mysql/migration/14.0.0-15.0.0.sql
@@ -100,6 +100,8 @@ UPDATE llx_facture_fourn SET multicurrency_total_ht = -multicurrency_total_ht WH
UPDATE llx_facture_fourn SET multicurrency_total_tva = -multicurrency_total_tva WHERE ((multicurrency_total_tva < 0 and total_tva > 0) OR (multicurrency_total_tva > 0 and total_tva < 0));
UPDATE llx_facture_fourn SET multicurrency_total_ttc = -multicurrency_total_ttc WHERE ((multicurrency_total_ttc < 0 and total_ttc > 0) OR (multicurrency_total_ttc > 0 and total_ttc < 0));
+ALTER TABLE llx_propaldet ADD COLUMN import_key varchar(14);
+
-- v15
@@ -504,3 +506,26 @@ INSERT INTO llx_c_action_trigger (code,label,description,elementtype,rang) value
INSERT INTO llx_c_action_trigger (code,label,description,elementtype,rang) values ('HOLIDAY_APPROVE','Holiday aprouved','Executed when a holiday is aprouved','holiday',803);
INSERT INTO llx_c_action_trigger (code,label,description,elementtype,rang) values ('HOLIDAY_CANCEL','Holiday canceled','Executed when a holiday is canceled','holiday',802);
INSERT INTO llx_c_action_trigger (code,label,description,elementtype,rang) values ('HOLIDAY_DELETE','Holiday deleted','Executed when a holiday is deleted','holiday',804);
+
+-- We do not delete old mexican legal forms because they may have been used. User will have to insert the new one manually not inserted because of conflict if he need them.
+--DELETE FROM llx_c_forme_juridique WHERE code IN ('15401', '15402', '15403', '15404', '15405', '15406');
+
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15401', '601 - General de Ley Personas Morales', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15402', '603 - Personas Morales con Fines no Lucrativos', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15403', '605 - Sueldos y Salarios e Ingresos Asimilados a Salarios', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15404', '606 - Arrendamiento', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15405', '607 - Régimen de Enajenación o Adquisición de Bienes', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15406', '608 - Demás ingresos', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15407', '610 - Residentes en el Extranjero sin Establecimiento Permanente en México', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15408', '611 - Ingresos por Dividendos (socios y accionistas)', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15409', '612 - Personas Físicas con Actividades Empresariales y Profesionales', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15410', '614 - Ingresos por intereses', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15411', '615 - Régimen de los ingresos por obtención de premios', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15412', '616 - Sin obligaciones fiscales', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15413', '620 - Sociedades Cooperativas de Producción que optan por diferir sus ingresos', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15414', '621 - Incorporación Fiscal', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15415', '622 - Actividades Agrícolas, Ganaderas, Silvícolas y Pesqueras', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15416', '623 - Opcional para Grupos de Sociedades', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15417', '624 - Coordinados', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15418', '625 - Régimen de las Actividades Empresariales con ingresos a través de Plataformas Tecnológicas', 1);
+INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154, '15419', '626 - Régimen Simplificado de Confianza', 1);
diff --git a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql
index 55218730381..b78e53bd287 100644
--- a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql
+++ b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql
@@ -96,4 +96,145 @@ CREATE TABLE llx_stock_mouvement_extrafields (
import_key varchar(14)
)ENGINE=innodb;
+ALTER TABLE llx_stock_mouvement_extrafields ADD INDEX idx_stock_mouvement_extrafields (fk_object);
+
+
+-- Facture fourn rec
+CREATE TABLE llx_facture_fourn_rec
+(
+ rowid integer AUTO_INCREMENT PRIMARY KEY,
+ titre varchar(200) NOT NULL,
+ ref_supplier varchar(180) NOT NULL,
+ entity integer DEFAULT 1 NOT NULL,
+ fk_soc integer NOT NULL,
+ datec datetime,
+ tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ suspended integer DEFAULT 0,
+ libelle varchar(255),
+ amount double(24, 8) DEFAULT 0 NOT NULL,
+ remise real DEFAULT 0,
+ vat_src_code varchar(10) DEFAULT '',
+ localtax1 double(24,8) DEFAULT 0,
+ localtax2 double(24,8) DEFAULT 0,
+ total_ht double(24,8) DEFAULT 0,
+ total_tva double(24,8) DEFAULT 0,
+ total_ttc double(24,8) DEFAULT 0,
+ fk_user_author integer,
+ fk_user_modif integer,
+ fk_projet integer,
+ fk_account integer,
+ fk_cond_reglement integer,
+ fk_mode_reglement integer,
+ date_lim_reglement date,
+ note_private text,
+ note_public text,
+ modelpdf varchar(255),
+ fk_multicurrency integer,
+ multicurrency_code varchar(3),
+ multicurrency_tx double(24,8) DEFAULT 1,
+ multicurrency_total_ht double(24,8) DEFAULT 0,
+ multicurrency_total_tva double(24,8) DEFAULT 0,
+ multicurrency_total_ttc double(24,8) DEFAULT 0,
+ usenewprice integer DEFAULT 0,
+ frequency integer,
+ unit_frequency varchar(2) DEFAULT 'm',
+ date_when datetime DEFAULT NULL,
+ date_last_gen datetime DEFAULT NULL,
+ nb_gen_done integer DEFAULT NULL,
+ nb_gen_max integer DEFAULT NULL,
+ auto_validate integer DEFAULT 0,
+ generate_pdf integer DEFAULT 1
+)ENGINE=innodb;
+
+ALTER TABLE llx_facture_fourn_rec ADD UNIQUE INDEX uk_facture_fourn_rec_ref (titre, entity);
+ALTER TABLE llx_facture_fourn_rec ADD UNIQUE INDEX uk_facture_fourn_rec_ref_supplier (ref_supplier, fk_soc, entity);
+ALTER TABLE llx_facture_fourn_rec ADD INDEX idx_facture_fourn_rec_date_lim_reglement (date_lim_reglement);
+ALTER TABLE llx_facture_fourn_rec ADD INDEX idx_facture_fourn_rec_fk_soc (fk_soc);
+ALTER TABLE llx_facture_fourn_rec ADD INDEX idx_facture_fourn_rec_fk_user_author (fk_user_author);
+ALTER TABLE llx_facture_fourn_rec ADD INDEX idx_facture_fourn_rec_fk_projet (fk_projet);
+ALTER TABLE llx_facture_fourn_rec ADD CONSTRAINT fk_facture_fourn_rec_fk_soc FOREIGN KEY (fk_soc) REFERENCES llx_societe (rowid);
+ALTER TABLE llx_facture_fourn_rec ADD CONSTRAINT fk_facture_fourn_rec_fk_user_author FOREIGN KEY (fk_user_author) REFERENCES llx_user (rowid);
+ALTER TABLE llx_facture_fourn_rec ADD CONSTRAINT fk_facture_fourn_rec_fk_projet FOREIGN KEY (fk_projet) REFERENCES llx_projet (rowid);
+
+CREATE TABLE llx_facture_fourn_rec_extrafields
+(
+ rowid integer AUTO_INCREMENT PRIMARY KEY,
+ tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ fk_object integer NOT NULL,
+ import_key varchar(14) -- import key
+) ENGINE=innodb;
+
+ALTER TABLE llx_facture_fourn_rec_extrafields ADD INDEX idx_facture_fourn_rec_extrafields (fk_object);
+
+CREATE TABLE llx_facture_fourn_det_rec
+(
+ rowid integer AUTO_INCREMENT PRIMARY KEY,
+ fk_facture_fourn integer NOT NULL,
+ fk_parent_line integer NULL,
+ fk_product integer NULL,
+ ref varchar(50),
+ label varchar(255) DEFAULT NULL,
+ description text,
+ pu_ht double(24,8),
+ pu_ttc double(24,8),
+ qty real,
+ remise_percent real DEFAULT 0,
+ fk_remise_except integer NULL,
+ vat_src_code varchar(10) DEFAULT '',
+ tva_tx double(7,4),
+ localtax1_tx double(7,4) DEFAULT 0,
+ localtax1_type varchar(10) NULL,
+ localtax2_tx double(7,4) DEFAULT 0,
+ localtax2_type varchar(10) NULL,
+ total_ht double(24,8),
+ total_tva double(24,8),
+ total_localtax1 double(24,8) DEFAULT 0,
+ total_localtax2 double(24,8) DEFAULT 0,
+ total_ttc double(24,8),
+ product_type integer DEFAULT 0,
+ date_start integer DEFAULT NULL,
+ date_end integer DEFAULT NULL,
+ info_bits integer DEFAULT 0,
+ special_code integer UNSIGNED DEFAULT 0,
+ rang integer DEFAULT 0,
+ fk_unit integer DEFAULT NULL,
+ import_key varchar(14),
+ fk_user_author integer,
+ fk_user_modif integer,
+ fk_multicurrency integer,
+ multicurrency_code varchar(3),
+ multicurrency_subprice double(24,8) DEFAULT 0,
+ multicurrency_total_ht double(24,8) DEFAULT 0,
+ multicurrency_total_tva double(24,8) DEFAULT 0,
+ multicurrency_total_ttc double(24,8) DEFAULT 0
+)ENGINE=innodb;
+
+ALTER TABLE llx_facture_fourn_det_rec ADD CONSTRAINT fk_facture_fourn_det_rec_fk_unit FOREIGN KEY (fk_unit) REFERENCES llx_c_units (rowid);
+
+CREATE TABLE llx_facture_fourn_det_rec_extrafields
+(
+ rowid integer AUTO_INCREMENT PRIMARY KEY,
+ tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ fk_object integer NOT NULL, -- object id
+ import_key varchar(14) -- import key
+)ENGINE=innodb;
+
+ALTER TABLE llx_facture_fourn_det_rec_extrafields ADD INDEX idx_facture_fourn_det_rec_extrafields (fk_object);
+
+ALTER TABLE llx_facture_fourn ADD COLUMN fk_fac_rec_source integer;
+
ALTER TABLE llx_mrp_mo ADD COLUMN fk_parent_line integer;
+
+ALTER TABLE llx_projet_task ADD COLUMN status integer DEFAULT 1 NOT NULL;
+
+ALTER TABLE llx_product_attribute_value MODIFY COLUMN ref VARCHAR(180) NOT NULL;
+ALTER TABLE llx_product_attribute_value MODIFY COLUMN value VARCHAR(255) NOT NULL;
+ALTER TABLE llx_product_attribute_value ADD COLUMN position INTEGER NOT NULL DEFAULT 0;
+ALTER TABLE llx_product_attribute CHANGE rang position INTEGER DEFAULT 0 NOT NULL;
+
+
+ALTER TABLE llx_advtargetemailing RENAME TO llx_mailing_advtarget;
+
+ALTER TABLE llx_mailing ADD UNIQUE uk_mailing(titre, entity);
+
+
diff --git a/htdocs/install/mysql/tables/llx_asset.key.sql b/htdocs/install/mysql/tables/llx_asset-asset.key.sql
similarity index 100%
rename from htdocs/install/mysql/tables/llx_asset.key.sql
rename to htdocs/install/mysql/tables/llx_asset-asset.key.sql
diff --git a/htdocs/install/mysql/tables/llx_asset.sql b/htdocs/install/mysql/tables/llx_asset-asset.sql
similarity index 100%
rename from htdocs/install/mysql/tables/llx_asset.sql
rename to htdocs/install/mysql/tables/llx_asset-asset.sql
diff --git a/htdocs/install/mysql/tables/llx_asset_extrafields.key.sql b/htdocs/install/mysql/tables/llx_asset_extrafields-asset.key.sql
similarity index 100%
rename from htdocs/install/mysql/tables/llx_asset_extrafields.key.sql
rename to htdocs/install/mysql/tables/llx_asset_extrafields-asset.key.sql
diff --git a/htdocs/install/mysql/tables/llx_asset_extrafields.sql b/htdocs/install/mysql/tables/llx_asset_extrafields-asset.sql
similarity index 100%
rename from htdocs/install/mysql/tables/llx_asset_extrafields.sql
rename to htdocs/install/mysql/tables/llx_asset_extrafields-asset.sql
diff --git a/htdocs/install/mysql/tables/llx_asset_type.key.sql b/htdocs/install/mysql/tables/llx_asset_type-asset.key.sql
similarity index 100%
rename from htdocs/install/mysql/tables/llx_asset_type.key.sql
rename to htdocs/install/mysql/tables/llx_asset_type-asset.key.sql
diff --git a/htdocs/install/mysql/tables/llx_asset_type.sql b/htdocs/install/mysql/tables/llx_asset_type-asset.sql
similarity index 100%
rename from htdocs/install/mysql/tables/llx_asset_type.sql
rename to htdocs/install/mysql/tables/llx_asset_type-asset.sql
diff --git a/htdocs/install/mysql/tables/llx_asset_type_extrafields.key.sql b/htdocs/install/mysql/tables/llx_asset_type_extrafields-asset.key.sql
similarity index 100%
rename from htdocs/install/mysql/tables/llx_asset_type_extrafields.key.sql
rename to htdocs/install/mysql/tables/llx_asset_type_extrafields-asset.key.sql
diff --git a/htdocs/install/mysql/tables/llx_asset_type_extrafields.sql b/htdocs/install/mysql/tables/llx_asset_type_extrafields-asset.sql
similarity index 100%
rename from htdocs/install/mysql/tables/llx_asset_type_extrafields.sql
rename to htdocs/install/mysql/tables/llx_asset_type_extrafields-asset.sql
diff --git a/htdocs/install/mysql/tables/llx_facture_fourn.sql b/htdocs/install/mysql/tables/llx_facture_fourn.sql
index 683f15623a6..9ceff4e4fa9 100644
--- a/htdocs/install/mysql/tables/llx_facture_fourn.sql
+++ b/htdocs/install/mysql/tables/llx_facture_fourn.sql
@@ -61,6 +61,7 @@ create table llx_facture_fourn
fk_user_valid integer, -- user validating
fk_user_closing integer, -- user closing
+ fk_fac_rec_source integer, -- facture rec source
fk_facture_source integer, -- facture origine si facture avoir
fk_projet integer, -- projet auquel est associee la facture
diff --git a/htdocs/install/mysql/tables/llx_facture_fourn_det_rec.extrafields.key.sql b/htdocs/install/mysql/tables/llx_facture_fourn_det_rec.extrafields.key.sql
new file mode 100644
index 00000000000..221f7fa6398
--- /dev/null
+++ b/htdocs/install/mysql/tables/llx_facture_fourn_det_rec.extrafields.key.sql
@@ -0,0 +1,20 @@
+-- ========================================================================
+-- Copyright (C) 2017 ATM-CONSULTING
+--
+-- 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 .
+--
+-- ===================================================================
+
+
+ALTER TABLE llx_facture_fourn_det_rec_extrafields ADD INDEX llx_facture_fourn_det_rec_extrafields (fk_object);
\ No newline at end of file
diff --git a/htdocs/install/mysql/tables/llx_facture_fourn_det_rec.extrafields.sql b/htdocs/install/mysql/tables/llx_facture_fourn_det_rec.extrafields.sql
new file mode 100644
index 00000000000..096cab080fd
--- /dev/null
+++ b/htdocs/install/mysql/tables/llx_facture_fourn_det_rec.extrafields.sql
@@ -0,0 +1,24 @@
+-- ===================================================================
+--
+-- 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 .
+--
+-- ===================================================================
+
+create table llx_facture_fourn_det_rec_extrafields
+(
+ rowid integer AUTO_INCREMENT PRIMARY KEY,
+ tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ fk_object integer NOT NULL, -- object id
+ import_key varchar(14) -- import key
+)ENGINE=innodb;
diff --git a/htdocs/install/mysql/tables/llx_facture_fourn_det_rec.key.sql b/htdocs/install/mysql/tables/llx_facture_fourn_det_rec.key.sql
new file mode 100644
index 00000000000..6d0618c912a
--- /dev/null
+++ b/htdocs/install/mysql/tables/llx_facture_fourn_det_rec.key.sql
@@ -0,0 +1,18 @@
+-- ===================================================================
+--
+-- 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 .
+--
+-- ===================================================================
+
+ALTER TABLE llx_facture_fourn_det_rec ADD CONSTRAINT fk_facture_fourn_det_rec_fk_unit FOREIGN KEY (fk_unit) REFERENCES llx_c_units (rowid);
diff --git a/htdocs/install/mysql/tables/llx_facture_fourn_det_rec.sql b/htdocs/install/mysql/tables/llx_facture_fourn_det_rec.sql
new file mode 100644
index 00000000000..8f29f85230a
--- /dev/null
+++ b/htdocs/install/mysql/tables/llx_facture_fourn_det_rec.sql
@@ -0,0 +1,61 @@
+-- ===================================================================
+--
+-- 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 .
+--
+-- ===================================================================
+
+create table llx_facture_fourn_det_rec
+(
+ rowid integer AUTO_INCREMENT PRIMARY KEY,
+ fk_facture_fourn integer NOT NULL,
+ fk_parent_line integer NULL,
+ fk_product integer NULL,
+ ref varchar(50), -- supplier product ref
+ label varchar(255) DEFAULT NULL,
+ description text,
+ pu_ht double(24,8), -- unit price excluding tax
+ pu_ttc double(24,8), -- unit price with tax
+ qty real, -- quantity of product/service
+ remise_percent real DEFAULT 0, -- % de la remise ligne (exemple 20%)
+ fk_remise_except integer NULL, -- Lien vers table des remises fixes
+ vat_src_code varchar(10) DEFAULT '', -- Vat code used as source of vat fields. Not strict foreign key here.
+ tva_tx double(7,4), -- taux tva
+ localtax1_tx double(7,4) DEFAULT 0, -- localtax1 rate
+ localtax1_type varchar(10) NULL, -- localtax1 type
+ localtax2_tx double(7,4) DEFAULT 0, -- localtax2 rate
+ localtax2_type varchar(10) NULL, -- localtax2 type
+ total_ht double(24,8), -- Total HT de la ligne toute quantity et incluant remise ligne et globale
+ total_tva double(24,8), -- Total TVA de la ligne toute quantity et incluant remise ligne et globale
+ total_localtax1 double(24,8) DEFAULT 0, -- Total LocalTax1 for total quantity of line
+ total_localtax2 double(24,8) DEFAULT 0, -- total LocalTax2 for total quantity of line
+ total_ttc double(24,8), -- Total TTC de la ligne toute quantity et incluant remise ligne et globale
+ product_type integer DEFAULT 0,
+ date_start integer DEFAULT NULL, -- date debut si service
+ date_end integer DEFAULT NULL, -- date fin si service
+ info_bits integer DEFAULT 0, -- TVA NPR ou non
+ special_code integer UNSIGNED DEFAULT 0, -- code for special lines
+ rang integer DEFAULT 0, -- ordre d'affichage
+ fk_unit integer DEFAULT NULL,
+ import_key varchar(14),
+
+ fk_user_author integer, -- user making creation
+ fk_user_modif integer, -- user making last change
+
+ fk_multicurrency integer,
+ multicurrency_code varchar(3),
+ multicurrency_subprice double(24,8) DEFAULT 0,
+ multicurrency_total_ht double(24,8) DEFAULT 0,
+ multicurrency_total_tva double(24,8) DEFAULT 0,
+ multicurrency_total_ttc double(24,8) DEFAULT 0
+)ENGINE=innodb;
diff --git a/htdocs/install/mysql/tables/llx_facture_fourn_rec.extrafields.key.sql b/htdocs/install/mysql/tables/llx_facture_fourn_rec.extrafields.key.sql
new file mode 100644
index 00000000000..86dddf51624
--- /dev/null
+++ b/htdocs/install/mysql/tables/llx_facture_fourn_rec.extrafields.key.sql
@@ -0,0 +1,19 @@
+-- ===================================================================
+--
+-- 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 .
+--
+-- ===================================================================
+
+
+ALTER TABLE llx_facture_fourn_rec_extrafields ADD INDEX idx_facture_fourn_rec_extrafields (fk_object);
diff --git a/htdocs/install/mysql/tables/llx_facture_fourn_rec.extrafields.sql b/htdocs/install/mysql/tables/llx_facture_fourn_rec.extrafields.sql
new file mode 100644
index 00000000000..d1f5bd80e41
--- /dev/null
+++ b/htdocs/install/mysql/tables/llx_facture_fourn_rec.extrafields.sql
@@ -0,0 +1,7 @@
+create table llx_facture_fourn_rec_extrafields
+(
+ rowid integer AUTO_INCREMENT PRIMARY KEY,
+ tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ fk_object integer NOT NULL,
+ import_key varchar(14) -- import key
+) ENGINE=innodb;
\ No newline at end of file
diff --git a/htdocs/install/mysql/tables/llx_facture_fourn_rec.key.sql b/htdocs/install/mysql/tables/llx_facture_fourn_rec.key.sql
new file mode 100644
index 00000000000..c5a451e030f
--- /dev/null
+++ b/htdocs/install/mysql/tables/llx_facture_fourn_rec.key.sql
@@ -0,0 +1,27 @@
+-- ============================================================================
+--
+-- 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 .
+--
+-- ============================================================================
+
+
+ALTER TABLE llx_facture_fourn_rec ADD UNIQUE INDEX uk_facture_fourn_rec_ref (titre, entity);
+
+ALTER TABLE llx_facture_fourn_rec ADD INDEX idx_facture_fourn_rec_fk_soc (fk_soc);
+ALTER TABLE llx_facture_fourn_rec ADD INDEX idx_facture_fourn_rec_fk_user_author (fk_user_author);
+ALTER TABLE llx_facture_fourn_rec ADD INDEX idx_facture_fourn_rec_fk_projet (fk_projet);
+
+ALTER TABLE llx_facture_fourn_rec ADD CONSTRAINT fk_facture_fourn_rec_fk_soc FOREIGN KEY (fk_soc) REFERENCES llx_societe (rowid);
+ALTER TABLE llx_facture_fourn_rec ADD CONSTRAINT fk_facture_fourn_rec_fk_user_author FOREIGN KEY (fk_user_author) REFERENCES llx_user (rowid);
+ALTER TABLE llx_facture_fourn_rec ADD CONSTRAINT fk_facture_fourn_rec_fk_projet FOREIGN KEY (fk_projet) REFERENCES llx_projet (rowid);
diff --git a/htdocs/install/mysql/tables/llx_facture_fourn_rec.sql b/htdocs/install/mysql/tables/llx_facture_fourn_rec.sql
new file mode 100644
index 00000000000..edaa49e0ea1
--- /dev/null
+++ b/htdocs/install/mysql/tables/llx_facture_fourn_rec.sql
@@ -0,0 +1,77 @@
+-- ===========================================================================
+--
+-- 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 .
+--
+-- ===========================================================================
+
+create table llx_facture_fourn_rec
+(
+ rowid integer AUTO_INCREMENT PRIMARY KEY,
+ titre varchar(200) NOT NULL,
+ ref_supplier varchar(180) NOT NULL,
+ entity integer DEFAULT 1 NOT NULL, -- multi company id
+ fk_soc integer NOT NULL,
+
+ datec datetime, -- date de creation
+ tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- last modification date
+
+ suspended integer DEFAULT 0, -- 1=suspended
+
+ libelle varchar(255),
+ amount double(24, 8) DEFAULT 0 NOT NULL,
+ remise real DEFAULT 0,
+
+ vat_src_code varchar(10) DEFAULT '', -- Vat code used as source of vat fields. Not strict foreign key here.
+ localtax1 double(24,8) DEFAULT 0,
+ localtax2 double(24,8) DEFAULT 0,
+ total_ht double(24,8) DEFAULT 0,
+ total_tva double(24,8) DEFAULT 0,
+ total_ttc double(24,8) DEFAULT 0,
+
+ fk_user_author integer, -- user creating
+ fk_user_modif integer, -- user making last change
+
+ fk_projet integer, -- projet auquel est associe la facture
+
+ fk_account integer, -- bank account
+ fk_cond_reglement integer, -- condition de reglement (30 jours, fin de mois ...)
+ fk_mode_reglement integer, -- mode de reglement (CHQ, VIR, ...)
+ date_lim_reglement date, -- date limite de reglement
+
+ note_private text,
+ note_public text,
+ modelpdf varchar(255),
+
+ fk_multicurrency integer,
+ multicurrency_code varchar(3),
+ multicurrency_tx double(24,8) DEFAULT 1,
+ multicurrency_total_ht double(24,8) DEFAULT 0,
+ multicurrency_total_tva double(24,8) DEFAULT 0,
+ multicurrency_total_ttc double(24,8) DEFAULT 0,
+
+
+ -- Fields linked to the recurring behavior
+
+ usenewprice integer DEFAULT 0, -- update invoice with current price of product instead of recorded price
+ frequency integer, -- frequency (for example: 3 for every 3 month)
+ unit_frequency varchar(2) DEFAULT 'm', -- 'm' for month (date_when must be a day <= 28), 'y' for year, ...
+
+ date_when datetime DEFAULT NULL, -- date for next gen (when an invoice is generated, this field must be updated with next date)
+ date_last_gen datetime DEFAULT NULL, -- date for last gen (date with last successfull generation of invoice)
+ nb_gen_done integer DEFAULT NULL, -- nb of generation done (when an invoice is generated, this field must incremented)
+ nb_gen_max integer DEFAULT NULL, -- maximum number of generation
+ auto_validate integer DEFAULT 0, -- 0 to create in draft, 1 to create and validate the new invoice
+ generate_pdf integer DEFAULT 1 -- 0 disable pdf, 1 to generate pdf
+
+)ENGINE=innodb;
diff --git a/htdocs/install/mysql/tables/llx_mailing-mailing.key.sql b/htdocs/install/mysql/tables/llx_mailing-mailing.key.sql
new file mode 100644
index 00000000000..0791c1f2c27
--- /dev/null
+++ b/htdocs/install/mysql/tables/llx_mailing-mailing.key.sql
@@ -0,0 +1,20 @@
+-- ===================================================================
+-- Copyright (C) 2018 Laurent Destailleur
+--
+-- 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 .
+--
+-- ===================================================================
+
+
+ALTER TABLE llx_mailing ADD UNIQUE uk_mailing(titre, entity);
diff --git a/htdocs/install/mysql/tables/llx_mailing.sql b/htdocs/install/mysql/tables/llx_mailing-mailing.sql
similarity index 100%
rename from htdocs/install/mysql/tables/llx_mailing.sql
rename to htdocs/install/mysql/tables/llx_mailing-mailing.sql
diff --git a/htdocs/install/mysql/tables/llx_advtargetemailing.key.sql b/htdocs/install/mysql/tables/llx_mailing_advtarget-mailing.key.sql
similarity index 92%
rename from htdocs/install/mysql/tables/llx_advtargetemailing.key.sql
rename to htdocs/install/mysql/tables/llx_mailing_advtarget-mailing.key.sql
index 441dec301c2..12f9d4c6097 100644
--- a/htdocs/install/mysql/tables/llx_advtargetemailing.key.sql
+++ b/htdocs/install/mysql/tables/llx_mailing_advtarget-mailing.key.sql
@@ -14,4 +14,4 @@
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see .
-ALTER TABLE llx_advtargetemailing ADD UNIQUE INDEX uk_advtargetemailing_name (name);
+ALTER TABLE llx_mailing_advtarget ADD UNIQUE INDEX uk_advtargetemailing_name (name);
diff --git a/htdocs/install/mysql/tables/llx_advtargetemailing.sql b/htdocs/install/mysql/tables/llx_mailing_advtarget-mailing.sql
similarity index 97%
rename from htdocs/install/mysql/tables/llx_advtargetemailing.sql
rename to htdocs/install/mysql/tables/llx_mailing_advtarget-mailing.sql
index 34bd7eb53bf..a22ce23a955 100644
--- a/htdocs/install/mysql/tables/llx_advtargetemailing.sql
+++ b/htdocs/install/mysql/tables/llx_mailing_advtarget-mailing.sql
@@ -17,7 +17,7 @@
-- Table to setup advanced targeting for emailing
-- ============================================================================
-CREATE TABLE llx_advtargetemailing
+CREATE TABLE llx_mailing_advtarget
(
rowid integer NOT NULL auto_increment PRIMARY KEY,
name varchar(180) NOT NULL,
diff --git a/htdocs/install/mysql/tables/llx_mailing_cibles.key.sql b/htdocs/install/mysql/tables/llx_mailing_cibles-mailing.key.sql
similarity index 100%
rename from htdocs/install/mysql/tables/llx_mailing_cibles.key.sql
rename to htdocs/install/mysql/tables/llx_mailing_cibles-mailing.key.sql
diff --git a/htdocs/install/mysql/tables/llx_mailing_cibles.sql b/htdocs/install/mysql/tables/llx_mailing_cibles-mailing.sql
similarity index 100%
rename from htdocs/install/mysql/tables/llx_mailing_cibles.sql
rename to htdocs/install/mysql/tables/llx_mailing_cibles-mailing.sql
diff --git a/htdocs/install/mysql/tables/llx_product_attribute.sql b/htdocs/install/mysql/tables/llx_product_attribute.sql
index 362c104b95c..e4e60719046 100644
--- a/htdocs/install/mysql/tables/llx_product_attribute.sql
+++ b/htdocs/install/mysql/tables/llx_product_attribute.sql
@@ -21,10 +21,10 @@
CREATE TABLE llx_product_attribute
(
- rowid INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
- ref VARCHAR(255) NOT NULL,
- ref_ext VARCHAR(255) NULL,
- label VARCHAR(255) NOT NULL,
- rang INT DEFAULT 0 NOT NULL,
- entity INT DEFAULT 1 NOT NULL
+ rowid INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
+ ref VARCHAR(255) NOT NULL,
+ ref_ext VARCHAR(255) NULL,
+ label VARCHAR(255) NOT NULL,
+ position INTEGER DEFAULT 0 NOT NULL,
+ entity INTEGER DEFAULT 1 NOT NULL
)ENGINE=innodb;
diff --git a/htdocs/install/mysql/tables/llx_product_attribute_value.sql b/htdocs/install/mysql/tables/llx_product_attribute_value.sql
index 09e7d325d0d..e6821976ed2 100644
--- a/htdocs/install/mysql/tables/llx_product_attribute_value.sql
+++ b/htdocs/install/mysql/tables/llx_product_attribute_value.sql
@@ -21,9 +21,10 @@
CREATE TABLE llx_product_attribute_value
(
- rowid INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
- fk_product_attribute INT NOT NULL,
- ref VARCHAR(180) DEFAULT NULL,
- value VARCHAR(255) DEFAULT NULL,
- entity INT DEFAULT 1 NOT NULL
+ rowid INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
+ fk_product_attribute INTEGER NOT NULL,
+ ref VARCHAR(180) NOT NULL,
+ value VARCHAR(255) NOT NULL,
+ entity INTEGER DEFAULT 1 NOT NULL,
+ position INTEGER NOT NULL DEFAULT 0
)ENGINE=innodb;
diff --git a/htdocs/install/mysql/tables/llx_product_pricerules.key.sql b/htdocs/install/mysql/tables/llx_product_pricerules.key.sql
index 25ad889d8d2..c31dfc5e240 100644
--- a/htdocs/install/mysql/tables/llx_product_pricerules.key.sql
+++ b/htdocs/install/mysql/tables/llx_product_pricerules.key.sql
@@ -16,4 +16,7 @@
--
-- ===========================================================================
+-- Table used only when PRODUIT_MULTIPRICES is set (prices per level) + PRODUIT_MULTIPRICES_ALLOW_AUTOCALC_PRICELEVEL is set
+-- A checkbox become available on product to allow to set price rules
+
ALTER TABLE llx_product_pricerules ADD CONSTRAINT unique_level UNIQUE (level);
diff --git a/htdocs/install/mysql/tables/llx_product_pricerules.sql b/htdocs/install/mysql/tables/llx_product_pricerules.sql
index 4089d2f3a60..4e02eb0808f 100644
--- a/htdocs/install/mysql/tables/llx_product_pricerules.sql
+++ b/htdocs/install/mysql/tables/llx_product_pricerules.sql
@@ -16,6 +16,9 @@
--
-- ===========================================================================
+-- Table used only when PRODUIT_MULTIPRICES is set (prices per level) + PRODUIT_MULTIPRICES_ALLOW_AUTOCALC_PRICELEVEL is set
+-- A checkbox become available on product to allow to set price rules
+
CREATE TABLE llx_product_pricerules
(
rowid INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
diff --git a/htdocs/install/mysql/tables/llx_projet_task.sql b/htdocs/install/mysql/tables/llx_projet_task.sql
index 721dbf8355f..4c2461f2ff0 100644
--- a/htdocs/install/mysql/tables/llx_projet_task.sql
+++ b/htdocs/install/mysql/tables/llx_projet_task.sql
@@ -44,5 +44,6 @@ create table llx_projet_task
note_public text,
rang integer DEFAULT 0,
model_pdf varchar(255),
- import_key varchar(14) -- Import key
+ import_key varchar(14), -- Import key
+ status integer DEFAULT 1 NOT NULL
)ENGINE=innodb;
diff --git a/htdocs/install/mysql/tables/llx_propaldet.sql b/htdocs/install/mysql/tables/llx_propaldet.sql
index 103118d6b77..3c3bf830014 100644
--- a/htdocs/install/mysql/tables/llx_propaldet.sql
+++ b/htdocs/install/mysql/tables/llx_propaldet.sql
@@ -1,8 +1,9 @@
-- ===================================================================
--- Copyright (C) 2002-2003 Rodolphe Quiedeville
--- Copyright (C) 2005-2012 Regis Houssin
--- Copyright (C) 2010 Juanjo Menent
--- Copyright (C) 2012 Cédric Salvador
+-- Copyright (C) 2002-2003 Rodolphe Quiedeville
+-- Copyright (C) 2005-2012 Regis Houssin
+-- Copyright (C) 2010 Juanjo Menent
+-- Copyright (C) 2012 Cédric Salvador
+-- Copyright (C) 2022 OpenDSI
--
-- 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
@@ -21,53 +22,55 @@
create table llx_propaldet
(
- rowid integer AUTO_INCREMENT PRIMARY KEY,
- fk_propal integer NOT NULL,
- fk_parent_line integer NULL,
- fk_product integer NULL,
- label varchar(255) DEFAULT NULL,
- description text,
- fk_remise_except integer NULL, -- Lien vers table des remises fixes
- vat_src_code varchar(10) DEFAULT '', -- Vat code used as source of vat fields. Not strict foreign key here.
- tva_tx double(7,4) DEFAULT 0, -- Vat rate
- localtax1_tx double(7,4) DEFAULT 0, -- localtax1 rate
- localtax1_type varchar(10) NULL, -- localtax1 type
- localtax2_tx double(7,4) DEFAULT 0, -- localtax2 rate
- localtax2_type varchar(10) NULL, -- localtax2 type
- qty real, -- quantity
- remise_percent real DEFAULT 0, -- pourcentage de remise
- remise real DEFAULT 0, -- montant de la remise (obsolete)
- price real, -- prix final (obsolete)
- subprice double(24,8) DEFAULT 0, -- prix unitaire article
- total_ht double(24,8) DEFAULT 0, -- Total HT de la ligne toute quantite et incluant remise ligne et globale
- total_tva double(24,8) DEFAULT 0, -- Total TVA de la ligne toute quantite et incluant remise ligne et globale
- total_localtax1 double(24,8) DEFAULT 0, -- Total localtax1
- total_localtax2 double(24,8) DEFAULT 0, -- Total localtax2
- total_ttc double(24,8) DEFAULT 0, -- Total TTC de la ligne toute quantite et incluant remise ligne et globale
- product_type integer DEFAULT 0, -- 0 or 1. Value 9 may be used by some modules (amount of line may not be included into generated discount if value is 9).
- date_start datetime DEFAULT NULL, -- date debut si service
- date_end datetime DEFAULT NULL, -- date fin si service
- info_bits integer DEFAULT 0, -- TVA NPR ou non
-
- buy_price_ht double(24,8) DEFAULT 0, -- buying price
- fk_product_fournisseur_price integer DEFAULT NULL, -- reference of supplier price when line was added (may be used to update buy_price_ht current price when future invoice will be created)
-
- special_code integer DEFAULT 0, -- code for special lines (may be 1=transport, 2=ecotax, 3=option, moduleid=...)
- rang integer DEFAULT 0, -- ordre affichage sur la propal
- fk_unit integer DEFAULT NULL, -- lien vers table des unités
-
- fk_multicurrency integer,
- multicurrency_code varchar(3),
- multicurrency_subprice double(24,8) DEFAULT 0,
- multicurrency_total_ht double(24,8) DEFAULT 0,
- multicurrency_total_tva double(24,8) DEFAULT 0,
- multicurrency_total_ttc double(24,8) DEFAULT 0
+ rowid integer AUTO_INCREMENT PRIMARY KEY,
+ fk_propal integer NOT NULL,
+ fk_parent_line integer NULL,
+ fk_product integer NULL,
+ label varchar(255) DEFAULT NULL,
+ description text,
+ fk_remise_except integer NULL, -- Link to table of fixed discounts
+ vat_src_code varchar(10) DEFAULT '', -- Vat code used as source of vat fields. Not strict foreign key here.
+ tva_tx double(7,4) DEFAULT 0, -- Vat rate
+ localtax1_tx double(7,4) DEFAULT 0, -- localtax1 rate
+ localtax1_type varchar(10) NULL, -- localtax1 type
+ localtax2_tx double(7,4) DEFAULT 0, -- localtax2 rate
+ localtax2_type varchar(10) NULL, -- localtax2 type
+ qty real, -- quantity
+ remise_percent real DEFAULT 0, -- discount percentage
+ remise real DEFAULT 0, -- discount amount (obsolete)
+ price real, -- final price (obsolete)
+ subprice double(24,8) DEFAULT 0, -- unit price article
+ total_ht double(24,8) DEFAULT 0, -- Total excluding VAT of the line all quantities and including line and global discount
+ total_tva double(24,8) DEFAULT 0, -- Total VAT of the line any quantity and including discount line and global
+ total_localtax1 double(24,8) DEFAULT 0, -- Total localtax1
+ total_localtax2 double(24,8) DEFAULT 0, -- Total localtax2
+ total_ttc double(24,8) DEFAULT 0, -- Total TTC of the line all quantity and including line and global discount
+ product_type integer DEFAULT 0, -- 0 or 1. Value 9 may be used by some modules (amount of line may not be included into generated discount if value is 9).
+ date_start datetime DEFAULT NULL, -- start date if service
+ date_end datetime DEFAULT NULL, -- end date if service
+ info_bits integer DEFAULT 0, -- VAT NPR or not
+
+ buy_price_ht double(24,8) DEFAULT 0, -- buying price
+ fk_product_fournisseur_price integer DEFAULT NULL, -- reference of supplier price when line was added (may be used to update buy_price_ht current price when future invoice will be created)
+
+ special_code integer DEFAULT 0, -- code for special lines (may be 1=transport, 2=ecotax, 3=option, moduleid=...)
+ rang integer DEFAULT 0, -- order display on the propal
+ fk_unit integer DEFAULT NULL, -- link to table of units
+
+ fk_multicurrency integer,
+ multicurrency_code varchar(3),
+ multicurrency_subprice double(24,8) DEFAULT 0,
+ multicurrency_total_ht double(24,8) DEFAULT 0,
+ multicurrency_total_tva double(24,8) DEFAULT 0,
+ multicurrency_total_ttc double(24,8) DEFAULT 0,
+
+ import_key varchar(14)
)ENGINE=innodb;
--
--- Liste des codes pour special_code
+-- List of codes for special_code
--
--- 1 : frais de port
--- 2 : ecotaxe
--- 3 : produit/service propose en option
+-- 1 : shipping costs
+-- 2 : ecotax
+-- 3 : optional product/service
--
diff --git a/htdocs/install/mysql/tables/llx_stock_mouvement_extrafields.key.sql b/htdocs/install/mysql/tables/llx_stock_mouvement_extrafields.key.sql
new file mode 100644
index 00000000000..61909435b00
--- /dev/null
+++ b/htdocs/install/mysql/tables/llx_stock_mouvement_extrafields.key.sql
@@ -0,0 +1,21 @@
+-- ============================================================================
+-- Copyright (C) 2002-2004 Rodolphe Quiedeville
+-- Copyright (C) 2004-2005 Laurent Destailleur
+--
+-- 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 .
+--
+-- ============================================================================
+
+
+ALTER TABLE llx_stock_mouvement_extrafields ADD INDEX idx_stock_mouvement_extrafields (fk_object);
diff --git a/htdocs/install/mysql/tables/llx_ticket.key.sql b/htdocs/install/mysql/tables/llx_ticket-ticket.key.sql
similarity index 100%
rename from htdocs/install/mysql/tables/llx_ticket.key.sql
rename to htdocs/install/mysql/tables/llx_ticket-ticket.key.sql
diff --git a/htdocs/install/mysql/tables/llx_ticket.sql b/htdocs/install/mysql/tables/llx_ticket-ticket.sql
similarity index 100%
rename from htdocs/install/mysql/tables/llx_ticket.sql
rename to htdocs/install/mysql/tables/llx_ticket-ticket.sql
diff --git a/htdocs/install/mysql/tables/llx_ticket_extrafields.key.sql b/htdocs/install/mysql/tables/llx_ticket_extrafields-ticket.key.sql
similarity index 100%
rename from htdocs/install/mysql/tables/llx_ticket_extrafields.key.sql
rename to htdocs/install/mysql/tables/llx_ticket_extrafields-ticket.key.sql
diff --git a/htdocs/install/mysql/tables/llx_ticket_extrafields.sql b/htdocs/install/mysql/tables/llx_ticket_extrafields-ticket.sql
similarity index 100%
rename from htdocs/install/mysql/tables/llx_ticket_extrafields.sql
rename to htdocs/install/mysql/tables/llx_ticket_extrafields-ticket.sql
diff --git a/htdocs/knowledgemanagement/class/knowledgerecord.class.php b/htdocs/knowledgemanagement/class/knowledgerecord.class.php
index b241cb2d9e9..a2f03a64e41 100644
--- a/htdocs/knowledgemanagement/class/knowledgerecord.class.php
+++ b/htdocs/knowledgemanagement/class/knowledgerecord.class.php
@@ -115,7 +115,7 @@ class KnowledgeRecord extends CommonObject
'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>'1', 'position'=>1000, 'notnull'=>-1, 'visible'=>-2,),
'model_pdf' => array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>'1', 'position'=>1010, 'notnull'=>-1, 'visible'=>0,),
//'url' => array('type'=>'varchar(255)', 'label'=>'URL', 'enabled'=>'1', 'position'=>55, 'notnull'=>0, 'visible'=>-1, 'csslist'=>'tdoverflow200', 'help'=>'UrlForInfoPage'),
- 'fk_c_ticket_category' => array('type'=>'integer:CTicketCategory:ticket/class/cticketcategory.class.php:0::pos', 'label'=>'SuggestedForTicketsInGroup', 'enabled'=>'$conf->ticket->enabled', 'position'=>512, 'notnull'=>0, 'visible'=>-1, 'help'=>'YouCanLinkArticleToATicketCategory', 'csslist'=>'minwidth200 tdoverflowmax250'),
+ 'fk_c_ticket_category' => array('type'=>'integer:CTicketCategory:ticket/class/cticketcategory.class.php:0:(t.active:=:1):pos', 'label'=>'SuggestedForTicketsInGroup', 'enabled'=>'$conf->ticket->enabled', 'position'=>512, 'notnull'=>0, 'visible'=>-1, 'help'=>'YouCanLinkArticleToATicketCategory', 'csslist'=>'minwidth200 tdoverflowmax250'),
'status' => array('type'=>'integer', 'label'=>'Status', 'enabled'=>'1', 'position'=>1000, 'notnull'=>1, 'visible'=>5, 'default'=>0, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Draft', '1'=>'Validated', '9'=>'Obsolete'),),
);
public $rowid;
@@ -459,7 +459,7 @@ class KnowledgeRecord extends CommonObject
public function delete(User $user, $notrigger = false)
{
$error = 0;
- $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_member WHERE fk_member = ".((int) $this->rowid);
+ $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_knowledgemanagement WHERE fk_knowledgemanagement = ".((int) $this->id);
dol_syslog(get_class($this)."::delete", LOG_DEBUG);
$resql = $this->db->query($sql);
if (!$resql) {
@@ -791,7 +791,7 @@ class KnowledgeRecord extends CommonObject
global $action, $hookmanager;
$hookmanager->initHooks(array('knowledgerecorddao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
diff --git a/htdocs/knowledgemanagement/knowledgerecord_card.php b/htdocs/knowledgemanagement/knowledgerecord_card.php
index a388175dbcf..2fcf05a4393 100644
--- a/htdocs/knowledgemanagement/knowledgerecord_card.php
+++ b/htdocs/knowledgemanagement/knowledgerecord_card.php
@@ -175,10 +175,10 @@ if ($action == 'create') {
print '