diff --git a/ChangeLog b/ChangeLog
index 555258f3901..1a0a95aab9e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -27,6 +27,8 @@ NEW: A lot of addition of hooks.
Following changes may create regressions for some external modules, but were necessary to make Dolibarr better:
+* There is a new specific permission to be allowed to enter timesheets. If you use timesheet, don't forget to give the new permission (disable and
+ enable the module project if it is not visible).
* The default value for MAIN_SECURITY_CSRF_WITH_TOKEN has been set to 2. It means any POST and any GET request that contains the "action" or "massaction"
with a value of a sensitive action must also a valid token parameter (With previous value 1, only POST was concerned). Note: With value 3, any URL
with parameter "action" or "massaction" need the token, whatever is the value of the action.
diff --git a/README.md b/README.md
index 4e120a4cb91..5559613eaa2 100644
--- a/README.md
+++ b/README.md
@@ -111,7 +111,7 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog)
- Customers/Prospects + Contacts management
- Opportunities or Leads management
-- Commercial proposals management
+- Commercial proposals management (online signing)
- Customer Orders management
- Contracts/Subscription management
- Interventions management
@@ -129,11 +129,11 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog)
- Supplier Invoices/credit notes and payment management
- INCOTERMS
- Finance / Accounting
+ Finance/Accounting
-- Invoices / Payments
+- Invoices/Payments
- Bank accounts management
-- Direct debit orders management (European SEPA)
+- Direct debit and Credit transfer management (European SEPA)
- Accounting management
- Donations management
- Loan management
@@ -142,14 +142,14 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog)
Collaboration
-- Shared calendar/agenda (with ical and vcal export for third party tools integration)
+- Shared calendar/agenda (with ical and vcal import/export for third party tools integration)
- Projects & Tasks management
- Ticket System
- Surveys
HR
-- Employee's leave requests management
+- Employee's leaves management
- Expense reports
- Recruitment management
- Timesheets
@@ -157,16 +157,14 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog)
### Other application/modules
- Electronic Document Management (EDM)
-- Bookmarks management
+- Bookmarks
- Reporting
- Data export/import
- Barcodes
-- Margin calculations
- LDAP connectivity
- ClickToDial integration
- Mass emailing
- RSS integration
-- Skype integration
- Social platforms linking
- Payment platforms integration (PayPal, Stripe, Paybox...)
- Email-Collector
@@ -175,13 +173,12 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog)
### Other general features
-- Localization in most major languages
-- Multi-Language Support
+- Multi-Language Support (Localization in most major languages)
- Multi-Users and groups with finely grained rights
- Multi-Currency
- Multi-Company (by adding of an external module)
- Very user friendly and easy to use
-- customizable Dashboard
+- Customizable dashboards
- Highly customizable: enable only the modules you need, add user personalized fields, choose your skin, several menu managers (can be used by internal users as a back-office with a particular menu, or by external users as a front-office with another one)
- APIs (REST, SOAP)
- Code that is easy to understand, maintain and develop (PHP with no heavy framework; trigger and hook architecture)
@@ -191,8 +188,9 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog)
- Canadian double taxes (federal/province) and other countries using cumulative VAT
- Tunisian tax stamp
- Argentina invoice numbering using A,B,C...
+ - ZATCA e-invoicing QR-Code
- Compatible with [European directives](https://europa.eu/legislation_summaries/taxation/l31057_en.htm) (2006/112/CE ... 2010/45/UE)
- - Compatible with European GDPR rules
+ - Compatible with data privacy rules (europe GDPR, ...)
- ...
- Flexible PDF & ODT generation for invoices, proposals, orders...
- ...
@@ -244,6 +242,7 @@ Follow Dolibarr project on:
- [Facebook](https://www.facebook.com/dolibarr)
- [Twitter](https://www.twitter.com/dolibarr)
- [LinkedIn](https://www.linkedin.com/company/association-dolibarr)
+- [Reddit](https://www.reddit.com/r/Dolibarr_ERP_CRM/)
- [YouTube](https://www.youtube.com/user/DolibarrERPCRM)
- [GitHub](https://github.com/Dolibarr/dolibarr)
diff --git a/htdocs/accountancy/admin/card.php b/htdocs/accountancy/admin/card.php
index 91d8257ea7f..f2137d84af9 100644
--- a/htdocs/accountancy/admin/card.php
+++ b/htdocs/accountancy/admin/card.php
@@ -300,7 +300,7 @@ if ($action == 'create') {
// Edit mode
if ($action == 'update') {
- print dol_get_fiche_head($head, 'card', $langs->trans('AccountAccounting'), 0, 'billr');
+ print dol_get_fiche_head($head, 'card', $langs->trans('AccountAccounting'), 0, 'accounting_account');
print '
';
- print ' ';
+ print '
';
} // END IF not edit
+// List of available record in database
+dol_syslog("htdocs/admin/dict", LOG_DEBUG);
+$resql = $db->query($sql);
+if (!$resql) {
+ dol_print_error($db);
+ exit;
+}
+
+$num = $db->num_rows($resql);
+
print '';
} else {
if ($selected) {
$this->load_cache_conditions_paiements();
if (isset($this->cache_conditions_paiements[$selected])) {
- print $this->cache_conditions_paiements[$selected]['label'];
+ $label = $this->cache_conditions_paiements[$selected]['label'];
+
+ if (! empty($this->cache_conditions_paiements[$selected]['deposit_percent'])) {
+ $label = str_replace('__DEPOSIT_PERCENT__', $deposit_percent > 0 ? $deposit_percent : $this->cache_conditions_paiements[$selected]['deposit_percent'], $label);
+ }
+
+ print $label;
} else {
$langs->load('errors');
print $langs->trans('ErrorNotInDictionaryPaymentConditions');
@@ -7226,6 +7282,8 @@ class Form
unset($adherenttmpselect);
}
+ $urloption = '';
+
$out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/adherents/ajax/adherents.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
if (empty($hidelabel)) $out .= $langs->trans("RefOrLabel").' : ';
@@ -7240,7 +7298,9 @@ class Form
$out .= img_picto($langs->trans("Search"), 'search');
}
} else {
- $out .= $this->selectMembersList($selected, $htmlname, $filtertype, $limit, $status, 0, $socid, $showempty, $forcecombo, $morecss);
+ $filterkey = '';
+
+ $out .= $this->selectMembersList($selected, $htmlname, $filtertype, $limit, $filterkey, $status, 0, $showempty, $forcecombo, $morecss);
}
if (empty($nooutput)) print $out;
@@ -7255,8 +7315,8 @@ class Form
* @param string $htmlname Name of select html
* @param string $filtertype Filter on adherent type
* @param int $limit Limit on number of returned lines
- * @param string $filterkey Filter on adherent ref or subject
- * @param int $status Ticket status
+ * @param string $filterkey Filter on member status
+ * @param int $status Member status
* @param int $outputmode 0=HTML select string, 1=Array
* @param string $showempty '' to not show empty line. Translation key to show an empty line. '1' show empty line with no text.
* @param int $forcecombo Force to use combo box
@@ -7270,7 +7330,7 @@ class Form
$out = '';
$outarray = array();
- $selectFields = " p.rowid, p.ref";
+ $selectFields = " p.rowid, p.ref, p.firstname, p.lastname";
$sql = "SELECT ";
$sql .= $selectFields;
@@ -7280,21 +7340,23 @@ class Form
// Add criteria on ref/label
if ($filterkey != '') {
$sql .= ' AND (';
- $prefix = empty($conf->global->TICKET_DONOTSEARCH_ANYWHERE) ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
+ $prefix = empty($conf->global->MEMBER_DONOTSEARCH_ANYWHERE) ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
// For natural search
$scrit = explode(' ', $filterkey);
$i = 0;
if (count($scrit) > 1) $sql .= "(";
foreach ($scrit as $crit) {
if ($i > 0) $sql .= " AND ";
- $sql .= "p.ref LIKE '".$this->db->escape($prefix.$crit)."%'";
- $sql .= "";
+ $sql .= "(p.firstname LIKE '".$this->db->escape($prefix.$crit)."%'";
+ $sql .= " OR p.lastname LIKE '".$this->db->escape($prefix.$crit)."%')";
$i++;
}
if (count($scrit) > 1) $sql .= ")";
$sql .= ')';
}
-
+ if ($status != -1) {
+ $sql .= ' AND statut = '.((int) $status);
+ }
$sql .= $this->db->plimit($limit, 0);
// Build output string
@@ -7324,7 +7386,9 @@ class Form
} else {
if ($showempty && !is_numeric($showempty)) $textifempty = $langs->trans($showempty);
}
- if ($showempty) $out .= '';
+ if ($showempty) {
+ $out .= '';
+ }
$i = 0;
while ($num && $i < $num) {
@@ -7333,6 +7397,7 @@ class Form
$objp = $this->db->fetch_object($result);
$this->constructMemberListOption($objp, $opt, $optJson, $selected, $filterkey);
+
// Add new entry
// "key" value of json key array is used by jQuery automatically as selected value
// "label" value of json key array is used by jQuery automatically as text for combo box
@@ -7367,28 +7432,23 @@ class Form
protected function constructMemberListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
{
$outkey = '';
- $outval = '';
- $outref = '';
$outlabel = '';
$outtype = '';
- $label = $objp->label;
-
$outkey = $objp->rowid;
- $outref = $objp->ref;
- $outlabel = $objp->label;
- $outtype = $objp->fk_product_type;
+ $outlabel = dolGetFirstLastname($objp->firstname, $objp->lastname);
+ $outtype = $objp->fk_adherent_type;
$opt = '\n";
- $optJson = array('key'=>$outkey, 'value'=>$outref, 'type'=>$outtype);
+
+ $optJson = array('key'=>$outkey, 'value'=>$outlabel, 'type'=>$outtype);
}
/**
diff --git a/htdocs/core/class/ldap.class.php b/htdocs/core/class/ldap.class.php
index 9e2c45fd634..6f54229c993 100644
--- a/htdocs/core/class/ldap.class.php
+++ b/htdocs/core/class/ldap.class.php
@@ -234,7 +234,7 @@ class Ldap
}
}
- if (is_resource($this->connection)) {
+ if (is_resource($this->connection) || is_object($this->connection)) {
// Upgrade connexion to TLS, if requested by the configuration
if (!empty($conf->global->LDAP_SERVER_USE_TLS)) {
// For test/debug
diff --git a/htdocs/core/class/translate.class.php b/htdocs/core/class/translate.class.php
index 27f3ca1c836..94bd36799fc 100644
--- a/htdocs/core/class/translate.class.php
+++ b/htdocs/core/class/translate.class.php
@@ -1089,11 +1089,12 @@ class Translate
$i = 0;
while ($i < $num) {
$obj = $db->fetch_object($resql);
-
- // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
- $this->cache_currencies[$obj->code_iso]['label'] = ($obj->code_iso && $this->trans("Currency".$obj->code_iso) != "Currency".$obj->code_iso ? $this->trans("Currency".$obj->code_iso) : ($obj->label != '-' ? $obj->label : ''));
- $this->cache_currencies[$obj->code_iso]['unicode'] = (array) json_decode($obj->unicode, true);
- $label[$obj->code_iso] = $this->cache_currencies[$obj->code_iso]['label'];
+ if ($obj) {
+ // If a translation exists, we use it lese we use the default label
+ $this->cache_currencies[$obj->code_iso]['label'] = ($obj->code_iso && $this->trans("Currency".$obj->code_iso) != "Currency".$obj->code_iso ? $this->trans("Currency".$obj->code_iso) : ($obj->label != '-' ? $obj->label : ''));
+ $this->cache_currencies[$obj->code_iso]['unicode'] = (array) json_decode($obj->unicode, true);
+ $label[$obj->code_iso] = $this->cache_currencies[$obj->code_iso]['label'];
+ }
$i++;
}
if (empty($currency_code)) {
diff --git a/htdocs/core/db/Database.interface.php b/htdocs/core/db/Database.interface.php
index e349072ddec..1d24b058614 100644
--- a/htdocs/core/db/Database.interface.php
+++ b/htdocs/core/db/Database.interface.php
@@ -502,8 +502,8 @@ interface Database
/**
* Returns the current line (as an object) for the resultset cursor
*
- * @param resource $resultset Cursor of the desired request
- * @return Object Object result line or false if KO or end of cursor
+ * @param resource|Connection $resultset Handler of the desired request
+ * @return Object Object result line or false if KO or end of cursor
*/
public function fetch_object($resultset);
// phpcs:enable
diff --git a/htdocs/core/db/pgsql.class.php b/htdocs/core/db/pgsql.class.php
index 74abf7a1e36..5a2a1c1b753 100644
--- a/htdocs/core/db/pgsql.class.php
+++ b/htdocs/core/db/pgsql.class.php
@@ -116,7 +116,7 @@ class DoliDBPgsql extends DoliDB
$this->connected = false;
$this->ok = false;
$this->error = 'Host, login or password incorrect';
- dol_syslog(get_class($this)."::DoliDBPgsql : Erreur Connect ".$this->error, LOG_ERR);
+ dol_syslog(get_class($this)."::DoliDBPgsql : Erreur Connect ".$this->error.'. Failed to connect to host='.$host.' port='.$port.' user='.$user, LOG_ERR);
}
// Si connexion serveur ok et si connexion base demandee, on essaie connexion base
@@ -423,7 +423,7 @@ class DoliDBPgsql extends DoliDB
}
// if local connection failed or not requested, use TCP/IP
- if (!$this->db) {
+ if (empty($this->db)) {
if (!$host) {
$host = "localhost";
}
@@ -432,7 +432,11 @@ class DoliDBPgsql extends DoliDB
}
$con_string = "host='".$host."' port='".$port."' dbname='".$name."' user='".$login."' password='".$passwd."'";
- $this->db = @pg_connect($con_string);
+ try {
+ $this->db = @pg_connect($con_string);
+ } catch (Exception $e) {
+ print $e->getMessage();
+ }
}
// now we test if at least one connect method was a success
@@ -580,7 +584,7 @@ class DoliDBPgsql extends DoliDB
{
// phpcs:enable
// If resultset not provided, we take the last used by connexion
- if (!is_resource($resultset)) {
+ if (!is_resource($resultset) && !is_object($resultset)) {
$resultset = $this->_results;
}
return pg_fetch_object($resultset);
@@ -597,7 +601,7 @@ class DoliDBPgsql extends DoliDB
{
// phpcs:enable
// If resultset not provided, we take the last used by connexion
- if (!is_resource($resultset)) {
+ if (!is_resource($resultset) && !is_object($resultset)) {
$resultset = $this->_results;
}
return pg_fetch_array($resultset);
@@ -614,7 +618,7 @@ class DoliDBPgsql extends DoliDB
{
// phpcs:enable
// Si le resultset n'est pas fourni, on prend le dernier utilise sur cette connexion
- if (!is_resource($resultset)) {
+ if (!is_resource($resultset) && !is_object($resultset)) {
$resultset = $this->_results;
}
return pg_fetch_row($resultset);
@@ -632,7 +636,7 @@ class DoliDBPgsql extends DoliDB
{
// phpcs:enable
// If resultset not provided, we take the last used by connexion
- if (!is_resource($resultset)) {
+ if (!is_resource($resultset) && !is_object($resultset)) {
$resultset = $this->_results;
}
return pg_num_rows($resultset);
@@ -650,7 +654,7 @@ class DoliDBPgsql extends DoliDB
{
// phpcs:enable
// If resultset not provided, we take the last used by connexion
- if (!is_resource($resultset)) {
+ if (!is_resource($resultset) && !is_object($resultset)) {
$resultset = $this->_results;
}
// pgsql necessite un resultset pour cette fonction contrairement
@@ -668,11 +672,11 @@ class DoliDBPgsql extends DoliDB
public function free($resultset = null)
{
// If resultset not provided, we take the last used by connexion
- if (!is_resource($resultset)) {
+ if (!is_resource($resultset) && !is_object($resultset)) {
$resultset = $this->_results;
}
// Si resultset en est un, on libere la memoire
- if (is_resource($resultset)) {
+ if (is_resource($resultset) || is_object($resultset)) {
pg_free_result($resultset);
}
}
@@ -916,7 +920,8 @@ class DoliDBPgsql extends DoliDB
// Test charset match LC_TYPE (pgsql error otherwise)
//print $charset.' '.setlocale(LC_CTYPE,'0'); exit;
- $sql = "CREATE DATABASE '".$this->escape($database)."' OWNER '".$this->escape($owner)."' ENCODING '".$this->escape($charset)."'";
+ // NOTE: Do not use ' around the database name
+ $sql = "CREATE DATABASE ".$this->escape($database)." OWNER '".$this->escape($owner)."' ENCODING '".$this->escape($charset)."'";
dol_syslog($sql, LOG_DEBUG);
$ret = $this->query($sql);
return $ret;
diff --git a/htdocs/core/js/lib_head.js.php b/htdocs/core/js/lib_head.js.php
index 2bf03129210..ac3de08af10 100644
--- a/htdocs/core/js/lib_head.js.php
+++ b/htdocs/core/js/lib_head.js.php
@@ -127,6 +127,19 @@ $langs->trans("FridayMin"),
$langs->trans("SaturdayMin")
);
+
+$dec = ',';
+$thousand = ' ';
+if ($langs->transnoentitiesnoconv("SeparatorDecimal") != "SeparatorDecimal") {
+ $dec = $langs->transnoentitiesnoconv("SeparatorDecimal");
+}
+if ($langs->transnoentitiesnoconv("SeparatorThousand") != "SeparatorThousand") {
+ $thousand = $langs->transnoentitiesnoconv("SeparatorThousand");
+}
+if ($thousand == 'Space') {
+ $thousand = ' ';
+}
+
?>
// Javascript libraries for Dolibarr ERP CRM (https://www.dolibarr.org)
@@ -136,6 +149,7 @@ var tradMonthsShort = ;
var tradDays = ;
var tradDaysShort = ;
var tradDaysMin = ;
+var currencyCache = cache_currencies) ?>;
// For JQuery date picker
$(document).ready(function() {
@@ -1091,22 +1105,87 @@ function getParameterByName(name, valueifnotfound)
// Another solution, easier, to build a javascript rounding function
function dolroundjs(number, decimals) { return +(Math.round(number + "e+" + decimals) + "e-" + decimals); }
-
/**
* Function similar to PHP price()
*
+ * Example use:
+ * pricejs(13312.448, 'MT', 'EUR', 'fr_FR')
+ * // (depending on conf for 'MT'): '13 312.45 €'
+ *
+ * pricejs(343000.121, 'MT')
+ * // assuming conf for 'MT' is 2 and $langs->defaultlang is 'en_US': '343,000.12'
+ *
* @param {number|string} amount The amount to show
* @param {string} mode 'MT' or 'MU'
+ * @param {string} currency_code ISO code of currency (empty by default)
+ * @param {string} force_locale ISO code locale to use (if empty, will use Dolibarr's current locale code)
* @return {string} The amount with digits
+ *
*/
-function pricejs(amount, mode) {
+function pricejs(amount, mode = 'MT', currency_code = '', force_locale = '') {
var main_max_dec_shown = global->MAIN_MAX_DECIMALS_SHOWN); ?>;
var main_rounding_unit = global->MAIN_MAX_DECIMALS_UNIT; ?>;
var main_rounding_tot = global->MAIN_MAX_DECIMALS_TOT; ?>;
+ var main_decimal_separator = ;
+ var main_thousand_separator = ;
+ var locale_code = force_locale || defaultlang) ?>;
+ var amountAsLocalizedString;
+ var useIntl = Boolean(Intl && Intl.NumberFormat);
+ var nDigits;
+ if (currency_code === 'auto') currency_code = currency) ?>;
- if (mode == 'MU') return amount.toFixed(main_rounding_unit);
- if (mode == 'MT') return amount.toFixed(main_rounding_tot);
- return 'Bad value for parameter mode';
+ if (mode === 'MU') nDigits = main_rounding_unit;
+ else if (mode === 'MT') nDigits = main_rounding_tot;
+ else return 'Bad value for parameter mode';
+
+ if (useIntl) {
+ // simple version: let the browser decide how to format the number using the provided language / currency
+ // parameters
+ var formattingOptions = {
+ minimumFractionDigits: nDigits,
+ maximumFractionDigits: nDigits
+ };
+ if (currency_code) {
+ formattingOptions['style'] = 'currency';
+ formattingOptions['currency'] = currency_code;
+ }
+ return Intl.NumberFormat(locale_code.replace('_', '-'), formattingOptions).format(amount);
+ }
+
+ // No Intl -> attempt to format the number in a way similar to Dolibarr PHP's `price()` function
+ amountAsLocalizedString = amount.toFixed(nDigits).replace(
+ /((?!^)(?:\d{3})*)(?:\.(\d+))?$/,
+ (fullMatch, digitsByThree, decimals) =>
+ digitsByThree.replace(
+ /\d{3}/g,
+ (groupOfThree) => main_thousand_separator + groupOfThree
+ ) + (decimals !== undefined ? main_decimal_separator + decimals : '')
+ ).replace(/ /, ' ');
+ if (!currency_code) return amountAsLocalizedString;
+
+ // print with currency
+ var currency_symbol = currency_code;
+
+ // codes of languages / currencies where the symbol must be placed before the amount
+ var currencyBeforeAmountCodes = {
+ currency: ['AUD', 'CAD', 'CNY', 'COP', 'CLP', 'GBP', 'HKD', 'MXN', 'PEN', 'USD'],
+ language: ['nl_NL']
+ };
+
+ if (currencyCache[currency_code]
+ && currencyCache[currency_code]['unicode']
+ && currencyCache[currency_code]['unicode'].length) {
+ currency_symbol = currencyCache[currency_code]['unicode'].reduce(function (res, cur) {return res + cur}, '');
+ }
+
+ if (currencyBeforeAmountCodes.currency.indexOf(currency_code) >= 0
+ || currencyBeforeAmountCodes.language.indexOf(locale_code)) {
+ // if we use a language or a currency where the symbol is placed before the amount
+ return currency_symbol + amountAsLocalizedString;
+ }
+
+ // by default: currency symbol after the amount
+ return amountAsLocalizedString + ' ' + currency_symbol;
}
/**
@@ -1119,20 +1198,8 @@ function pricejs(amount, mode) {
function price2numjs(amount) {
if (amount == '') return '';
- transnoentitiesnoconv("SeparatorDecimal") != "SeparatorDecimal") {
- $dec = $langs->transnoentitiesnoconv("SeparatorDecimal");
- }
- if ($langs->transnoentitiesnoconv("SeparatorThousand") != "SeparatorThousand") {
- $thousand = $langs->transnoentitiesnoconv("SeparatorThousand");
- }
- if ($thousand == 'Space') {
- $thousand = ' ';
- }
- print "var dec='".dol_escape_js($dec)."'; var thousand='".dol_escape_js($thousand)."';\n"; // Set var in javascript
- ?>
+ var dec = ;
+ var thousand = ;
var main_max_dec_shown = global->MAIN_MAX_DECIMALS_SHOWN); ?>;
var main_rounding_unit = global->MAIN_MAX_DECIMALS_UNIT; ?>;
diff --git a/htdocs/core/lib/usergroups.lib.php b/htdocs/core/lib/usergroups.lib.php
index 9bc0a59cf86..e14302da340 100644
--- a/htdocs/core/lib/usergroups.lib.php
+++ b/htdocs/core/lib/usergroups.lib.php
@@ -29,10 +29,10 @@
/**
* Prepare array with list of tabs
*
- * @param Object $object Object related to tabs
+ * @param User $object Object related to tabs
* @return array Array of tabs to show
*/
-function user_prepare_head($object)
+function user_prepare_head(User $object)
{
global $langs, $conf, $user, $db;
diff --git a/htdocs/core/login/functions_ldap.php b/htdocs/core/login/functions_ldap.php
index 1d86bd19549..022186b8de1 100644
--- a/htdocs/core/login/functions_ldap.php
+++ b/htdocs/core/login/functions_ldap.php
@@ -260,7 +260,7 @@ function check_user_password_ldap($usertotest, $passwordtotest, $entitytotest)
** 53 - Account inactive (manually locked out by administrator)
*/
dol_syslog("functions_ldap::check_user_password_ldap Authentication KO failed to connect to LDAP for '".$usertotest."'", LOG_NOTICE);
- if (is_resource($ldap->connection)) { // If connection ok but bind ko
+ if (is_resource($ldap->connection) || is_object($ldap->connection)) { // If connection ok but bind ko
$ldap->ldapErrorCode = ldap_errno($ldap->connection);
$ldap->ldapErrorText = ldap_error($ldap->connection);
dol_syslog("functions_ldap::check_user_password_ldap ".$ldap->ldapErrorCode." ".$ldap->ldapErrorText);
diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php
index 71abeda1f03..b579c9b0059 100644
--- a/htdocs/core/modules/DolibarrModules.class.php
+++ b/htdocs/core/modules/DolibarrModules.class.php
@@ -956,11 +956,11 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it
$err++;
} else {
$obj = $this->db->fetch_object($resql);
- $tmp = array();
- if ($obj->note) {
- $tmp = json_decode($obj->note, true);
- }
if ($obj) {
+ $tmp = array();
+ if ($obj->note) {
+ $tmp = json_decode($obj->note, true);
+ }
return array(
'authorid' => $tmp['authorid'],
'ip' => $tmp['ip'],
@@ -1054,16 +1054,16 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps,PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
/**
* Create tables and keys required by module:
- * - Files module.sql with create table instructions
- * - Then modules.key.sql with create keys instructions
+ * - Files table.sql or table-module.sql with create table instructions
+ * - Then table.key.sql or table-module.key.sql with create keys instructions
* - Then data_xxx.sql (usualy provided by external modules only)
* - Then update_xxx.sql (usualy provided by external modules only)
- * Files must be stored in directory defined by reldir (Example: '/install/mysql/tables' or '/module/sql/')
+ * Files must be stored in subdirectory 'tables' or 'data' into directory $reldir (Example: '/install/mysql/' or '/module/sql/')
* This function may also be called by :
- * - _load_tables('/install/mysql/tables/', 'modulename') into the this->init() of core module descriptors.
+ * - _load_tables('/install/mysql/', 'modulename') into the this->init() of core module descriptors.
* - _load_tables('/mymodule/sql/') into the this->init() of external module descriptors.
*
- * @param string $reldir Relative directory where to scan files. Example: '/install/mysql/tables' or '/module/sql/'
+ * @param string $reldir Relative directory where to scan files. Example: '/install/mysql/' or '/module/sql/'
* @param string $onlywithsuffix Only with the defined suffix
* @return int <=0 if KO, >0 if OK
*/
@@ -1084,112 +1084,147 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it
$ok = 1;
foreach ($conf->file->dol_document_root as $dirroot) {
if ($ok) {
- $dir = $dirroot.$reldir;
+ $dirsql = $dirroot.$reldir;
$ok = 0;
- $handle = @opendir($dir); // Dir may not exists
- if (is_resource($handle)) {
- $dirfound++;
+ // We will loop on xxx/, xxx/tables/, xxx/data/
+ $listofsubdir = array('', 'tables/', 'data/');
+ if ($this->db->type == 'pgsql') {
+ $listofsubdir[] = '../pgsql/functions/';
+ }
- // Run llx_mytable.sql files, then llx_mytable_*.sql
- $files = array();
- while (($file = readdir($handle)) !== false) {
- $files[] = $file;
- }
- sort($files);
- foreach ($files as $file) {
- if ($onlywithsuffix) {
- if (!preg_match('/\-'.preg_quote($onlywithsuffix, '/').'\./i', $file)) {
- //print 'File '.$file.' does not match suffix '.$onlywithsuffix.' so it is discarded '."\n";
- continue;
- } else {
- //print 'File '.$file.' match suffix '.$onlywithsuffix.' so we keep it '."\n";
+ foreach ($listofsubdir as $subdir) {
+ $dir = $dirsql.$subdir;
+
+ $handle = @opendir($dir); // Dir may not exists
+ if (is_resource($handle)) {
+ $dirfound++;
+
+ // Run llx_mytable.sql files, then llx_mytable_*.sql
+ $files = array();
+ while (($file = readdir($handle)) !== false) {
+ $files[] = $file;
+ }
+ sort($files);
+ foreach ($files as $file) {
+ if ($onlywithsuffix) {
+ if (!preg_match('/\-'.preg_quote($onlywithsuffix, '/').'\./i', $file)) {
+ //print 'File '.$file.' does not match suffix '.$onlywithsuffix.' so it is discarded '."\n";
+ continue;
+ } else {
+ //print 'File '.$file.' match suffix '.$onlywithsuffix.' so we keep it '."\n";
+ }
+ }
+ if (preg_match('/\.sql$/i', $file) && !preg_match('/\.key\.sql$/i', $file) && substr($file, 0, 4) == 'llx_') {
+ $result = run_sql($dir.$file, empty($conf->global->MAIN_DISPLAY_SQL_INSTALL_LOG) ? 1 : 0, '', 1);
+ if ($result <= 0) {
+ $error++;
+ }
}
}
- if (preg_match('/\.sql$/i', $file) && !preg_match('/\.key\.sql$/i', $file) && substr($file, 0, 4) == 'llx_' && substr($file, 0, 4) != 'data') {
- $result = run_sql($dir.$file, empty($conf->global->MAIN_DISPLAY_SQL_INSTALL_LOG) ? 1 : 0, '', 1);
- if ($result <= 0) {
- $error++;
+
+ rewinddir($handle);
+
+ // Run llx_mytable.key.sql files (Must be done after llx_mytable.sql) then then llx_mytable_*.key.sql
+ $files = array();
+ while (($file = readdir($handle)) !== false) {
+ $files[] = $file;
+ }
+ sort($files);
+ foreach ($files as $file) {
+ if ($onlywithsuffix) {
+ if (!preg_match('/\-'.preg_quote($onlywithsuffix, '/').'\./i', $file)) {
+ //print 'File '.$file.' does not match suffix '.$onlywithsuffix.' so it is discarded '."\n";
+ continue;
+ } else {
+ //print 'File '.$file.' match suffix '.$onlywithsuffix.' so we keep it '."\n";
+ }
+ }
+ if (preg_match('/\.key\.sql$/i', $file) && substr($file, 0, 4) == 'llx_') {
+ $result = run_sql($dir.$file, empty($conf->global->MAIN_DISPLAY_SQL_INSTALL_LOG) ? 1 : 0, '', 1);
+ if ($result <= 0) {
+ $error++;
+ }
}
}
- }
- rewinddir($handle);
+ rewinddir($handle);
- // Run llx_mytable.key.sql files (Must be done after llx_mytable.sql) then then llx_mytable_*.key.sql
- $files = array();
- while (($file = readdir($handle)) !== false) {
- $files[] = $file;
- }
- sort($files);
- foreach ($files as $file) {
- if ($onlywithsuffix) {
- if (!preg_match('/\-'.preg_quote($onlywithsuffix, '/').'\./i', $file)) {
- //print 'File '.$file.' does not match suffix '.$onlywithsuffix.' so it is discarded '."\n";
- continue;
- } else {
- //print 'File '.$file.' match suffix '.$onlywithsuffix.' so we keep it '."\n";
+ // Run functions-xxx.sql files (Must be done after llx_mytable.key.sql)
+ $files = array();
+ while (($file = readdir($handle)) !== false) {
+ $files[] = $file;
+ }
+ sort($files);
+ foreach ($files as $file) {
+ if ($onlywithsuffix) {
+ if (!preg_match('/\-'.preg_quote($onlywithsuffix, '/').'\./i', $file)) {
+ //print 'File '.$file.' does not match suffix '.$onlywithsuffix.' so it is discarded '."\n";
+ continue;
+ } else {
+ //print 'File '.$file.' match suffix '.$onlywithsuffix.' so we keep it '."\n";
+ }
+ }
+ if (preg_match('/\.sql$/i', $file) && !preg_match('/\.key\.sql$/i', $file) && substr($file, 0, 9) == 'functions') {
+ $result = run_sql($dir.$file, empty($conf->global->MAIN_DISPLAY_SQL_INSTALL_LOG) ? 1 : 0, '', 1);
+ if ($result <= 0) {
+ $error++;
+ }
}
}
- if (preg_match('/\.key\.sql$/i', $file) && substr($file, 0, 4) == 'llx_' && substr($file, 0, 4) != 'data') {
- $result = run_sql($dir.$file, empty($conf->global->MAIN_DISPLAY_SQL_INSTALL_LOG) ? 1 : 0, '', 1);
- if ($result <= 0) {
- $error++;
+
+ rewinddir($handle);
+
+ // Run data_xxx.sql files (Must be done after llx_mytable.key.sql)
+ $files = array();
+ while (($file = readdir($handle)) !== false) {
+ $files[] = $file;
+ }
+ sort($files);
+ foreach ($files as $file) {
+ if ($onlywithsuffix) {
+ if (!preg_match('/\-'.preg_quote($onlywithsuffix, '/').'\./i', $file)) {
+ //print 'File '.$file.' does not match suffix '.$onlywithsuffix.' so it is discarded '."\n";
+ continue;
+ } else {
+ //print 'File '.$file.' match suffix '.$onlywithsuffix.' so we keep it '."\n";
+ }
+ }
+ if (preg_match('/\.sql$/i', $file) && !preg_match('/\.key\.sql$/i', $file) && substr($file, 0, 4) == 'data') {
+ $result = run_sql($dir.$file, empty($conf->global->MAIN_DISPLAY_SQL_INSTALL_LOG) ? 1 : 0, '', 1);
+ if ($result <= 0) {
+ $error++;
+ }
}
}
- }
- rewinddir($handle);
+ rewinddir($handle);
- // Run data_xxx.sql files (Must be done after llx_mytable.key.sql)
- $files = array();
- while (($file = readdir($handle)) !== false) {
- $files[] = $file;
- }
- sort($files);
- foreach ($files as $file) {
- if ($onlywithsuffix) {
- if (!preg_match('/\-'.preg_quote($onlywithsuffix, '/').'\./i', $file)) {
- //print 'File '.$file.' does not match suffix '.$onlywithsuffix.' so it is discarded '."\n";
- continue;
- } else {
- //print 'File '.$file.' match suffix '.$onlywithsuffix.' so we keep it '."\n";
+ // Run update_xxx.sql files
+ $files = array();
+ while (($file = readdir($handle)) !== false) {
+ $files[] = $file;
+ }
+ sort($files);
+ foreach ($files as $file) {
+ if ($onlywithsuffix) {
+ if (!preg_match('/\-'.preg_quote($onlywithsuffix, '/').'\./i', $file)) {
+ //print 'File '.$file.' does not match suffix '.$onlywithsuffix.' so it is discarded '."\n";
+ continue;
+ } else {
+ //print 'File '.$file.' match suffix '.$onlywithsuffix.' so we keep it '."\n";
+ }
+ }
+ if (preg_match('/\.sql$/i', $file) && !preg_match('/\.key\.sql$/i', $file) && substr($file, 0, 6) == 'update') {
+ $result = run_sql($dir.$file, empty($conf->global->MAIN_DISPLAY_SQL_INSTALL_LOG) ? 1 : 0, '', 1);
+ if ($result <= 0) {
+ $error++;
+ }
}
}
- if (preg_match('/\.sql$/i', $file) && !preg_match('/\.key\.sql$/i', $file) && substr($file, 0, 4) == 'data') {
- $result = run_sql($dir.$file, empty($conf->global->MAIN_DISPLAY_SQL_INSTALL_LOG) ? 1 : 0, '', 1);
- if ($result <= 0) {
- $error++;
- }
- }
- }
- rewinddir($handle);
-
- // Run update_xxx.sql files
- $files = array();
- while (($file = readdir($handle)) !== false) {
- $files[] = $file;
+ closedir($handle);
}
- sort($files);
- foreach ($files as $file) {
- if ($onlywithsuffix) {
- if (!preg_match('/\-'.preg_quote($onlywithsuffix, '/').'\./i', $file)) {
- //print 'File '.$file.' does not match suffix '.$onlywithsuffix.' so it is discarded '."\n";
- continue;
- } else {
- //print 'File '.$file.' match suffix '.$onlywithsuffix.' so we keep it '."\n";
- }
- }
- if (preg_match('/\.sql$/i', $file) && !preg_match('/\.key\.sql$/i', $file) && substr($file, 0, 6) == 'update') {
- $result = run_sql($dir.$file, empty($conf->global->MAIN_DISPLAY_SQL_INSTALL_LOG) ? 1 : 0, '', 1);
- if ($result <= 0) {
- $error++;
- }
- }
- }
-
- closedir($handle);
}
if ($error == 0) {
diff --git a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php
index db961962ba6..fa9d83ea926 100644
--- a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php
+++ b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php
@@ -742,6 +742,9 @@ class pdf_einstein extends ModelePDFCommandes
$pdf->SetXY($posxval, $posy);
$lib_condition_paiement = $outputlangs->transnoentities("PaymentCondition".$object->cond_reglement_code) != ('PaymentCondition'.$object->cond_reglement_code) ? $outputlangs->transnoentities("PaymentCondition".$object->cond_reglement_code) : $outputlangs->convToOutputCharset($object->cond_reglement_doc ? $object->cond_reglement_doc : $object->cond_reglement_label);
$lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
+ if ($object->deposit_percent > 0) {
+ $lib_condition_paiement = str_replace('__DEPOSIT_PERCENT__', $object->deposit_percent, $lib_condition_paiement);
+ }
$pdf->MultiCell(67, 4, $lib_condition_paiement, 0, 'L');
$posy = $pdf->GetY() + 3;
diff --git a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php
index 560344a9eeb..b5f2ee5af43 100644
--- a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php
+++ b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php
@@ -960,6 +960,9 @@ class pdf_eratosthene extends ModelePDFCommandes
$pdf->SetXY($posxval, $posy);
$lib_condition_paiement = $outputlangs->transnoentities("PaymentCondition".$object->cond_reglement_code) != ('PaymentCondition'.$object->cond_reglement_code) ? $outputlangs->transnoentities("PaymentCondition".$object->cond_reglement_code) : $outputlangs->convToOutputCharset($object->cond_reglement_doc ? $object->cond_reglement_doc : $object->cond_reglement_label);
$lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
+ if ($object->deposit_percent > 0) {
+ $lib_condition_paiement = str_replace('__DEPOSIT_PERCENT__', $object->deposit_percent, $lib_condition_paiement);
+ }
$pdf->MultiCell(67, 4, $lib_condition_paiement, 0, 'L');
$posy = $pdf->GetY() + 3;
diff --git a/htdocs/core/modules/modAsset.class.php b/htdocs/core/modules/modAsset.class.php
index 2146de367e1..a217cb8d72c 100644
--- a/htdocs/core/modules/modAsset.class.php
+++ b/htdocs/core/modules/modAsset.class.php
@@ -240,7 +240,7 @@ class modAsset extends DolibarrModules
*/
public function init($options = '')
{
- $result = $this->_load_tables('/install/mysql/tables/', 'asset');
+ $result = $this->_load_tables('/install/mysql/', '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')
}
diff --git a/htdocs/core/modules/modDeplacement.class.php b/htdocs/core/modules/modDeplacement.class.php
index bceb313e120..450aa76258e 100644
--- a/htdocs/core/modules/modDeplacement.class.php
+++ b/htdocs/core/modules/modDeplacement.class.php
@@ -159,7 +159,7 @@ class modDeplacement extends DolibarrModules
*/
public function init($options = '')
{
- $result = $this->_load_tables('/install/mysql/tables/', 'deplacement');
+ $result = $this->_load_tables('/install/mysql/', 'deplacement');
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')
}
diff --git a/htdocs/core/modules/modDon.class.php b/htdocs/core/modules/modDon.class.php
index f2564cd3cc6..c5c790ca28c 100644
--- a/htdocs/core/modules/modDon.class.php
+++ b/htdocs/core/modules/modDon.class.php
@@ -155,7 +155,7 @@ class modDon extends DolibarrModules
{
global $conf;
- $result = $this->_load_tables('/install/mysql/tables/', 'deplacement');
+ $result = $this->_load_tables('/install/mysql/', 'don');
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')
}
diff --git a/htdocs/core/modules/modHRM.class.php b/htdocs/core/modules/modHRM.class.php
index bd81f06dae7..7df3bcc6dcf 100644
--- a/htdocs/core/modules/modHRM.class.php
+++ b/htdocs/core/modules/modHRM.class.php
@@ -280,7 +280,7 @@ class modHRM extends DolibarrModules
// Permissions
$this->remove($options);
- $result = $this->_load_tables('/install/mysql/tables/', 'hrm');
+ $result = $this->_load_tables('/install/mysql/', 'hrm');
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')
}
diff --git a/htdocs/core/modules/modIntracommreport.class.php b/htdocs/core/modules/modIntracommreport.class.php
index 50758f90f0c..25f26050ed0 100644
--- a/htdocs/core/modules/modIntracommreport.class.php
+++ b/htdocs/core/modules/modIntracommreport.class.php
@@ -138,7 +138,7 @@ class modIntracommreport extends DolibarrModules
{
global $conf;
- $result = $this->_load_tables('/install/mysql/tables/', 'intracommreport');
+ $result = $this->_load_tables('/install/mysql/', 'intracommreport');
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')
}
diff --git a/htdocs/core/modules/modKnowledgeManagement.class.php b/htdocs/core/modules/modKnowledgeManagement.class.php
index 93b44f31204..434cc9d6faf 100644
--- a/htdocs/core/modules/modKnowledgeManagement.class.php
+++ b/htdocs/core/modules/modKnowledgeManagement.class.php
@@ -442,7 +442,7 @@ class modKnowledgeManagement extends DolibarrModules
{
global $conf, $langs;
- $result = $this->_load_tables('/install/mysql/tables/', 'knowledgemanagement');
+ $result = $this->_load_tables('/install/mysql/', 'knowledgemanagement');
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')
}
diff --git a/htdocs/core/modules/modLoan.class.php b/htdocs/core/modules/modLoan.class.php
index e19ec1b81f8..8f9de88b83f 100644
--- a/htdocs/core/modules/modLoan.class.php
+++ b/htdocs/core/modules/modLoan.class.php
@@ -160,7 +160,7 @@ class modLoan extends DolibarrModules
{
global $conf;
- $result = $this->_load_tables('/install/mysql/tables/', 'loan');
+ $result = $this->_load_tables('/install/mysql/', 'loan');
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')
}
diff --git a/htdocs/core/modules/modMailing.class.php b/htdocs/core/modules/modMailing.class.php
index 1a31aad9c8b..7e3d4b6aeb1 100644
--- a/htdocs/core/modules/modMailing.class.php
+++ b/htdocs/core/modules/modMailing.class.php
@@ -159,7 +159,7 @@ class modMailing extends DolibarrModules
*/
public function init($options = '')
{
- $result = $this->_load_tables('/install/mysql/tables/', 'mailing');
+ $result = $this->_load_tables('/install/mysql/', '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')
}
diff --git a/htdocs/core/modules/modOpenSurvey.class.php b/htdocs/core/modules/modOpenSurvey.class.php
index 9cc9310cd19..04a8cd54082 100644
--- a/htdocs/core/modules/modOpenSurvey.class.php
+++ b/htdocs/core/modules/modOpenSurvey.class.php
@@ -184,7 +184,7 @@ class modOpenSurvey extends DolibarrModules
{
global $conf, $langs;
- $result = $this->_load_tables('/install/mysql/tables/', 'opensurvey');
+ $result = $this->_load_tables('/install/mysql/', 'opensurvey');
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')
}
diff --git a/htdocs/core/modules/modPartnership.class.php b/htdocs/core/modules/modPartnership.class.php
index c08cf66db06..f37d7d2403d 100644
--- a/htdocs/core/modules/modPartnership.class.php
+++ b/htdocs/core/modules/modPartnership.class.php
@@ -410,7 +410,7 @@ class modPartnership extends DolibarrModules
{
global $conf, $langs;
- $result = $this->_load_tables('/install/mysql/tables/', 'partnership');
+ $result = $this->_load_tables('/install/mysql/', 'partnership');
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')
}
diff --git a/htdocs/core/modules/modProjet.class.php b/htdocs/core/modules/modProjet.class.php
index f18a55ff6d8..f8b82e8faa3 100644
--- a/htdocs/core/modules/modProjet.class.php
+++ b/htdocs/core/modules/modProjet.class.php
@@ -152,7 +152,7 @@ class modProjet extends DolibarrModules
$r++;
$this->rights[$r][0] = 41; // id de la permission
- $this->rights[$r][1] = "Read projects and tasks (shared projects or projects I am contact for). Can also enter time consumed on assigned tasks (timesheet)"; // libelle de la permission
+ $this->rights[$r][1] = "Read projects and tasks (shared projects or projects I am contact for)"; // libelle de la permission
$this->rights[$r][2] = 'r'; // type de la permission (deprecie a ce jour)
$this->rights[$r][3] = 0; // La permission est-elle une permission par defaut
$this->rights[$r][4] = 'lire';
@@ -188,7 +188,7 @@ class modProjet extends DolibarrModules
$r++;
$this->rights[$r][0] = 142; // id de la permission
- $this->rights[$r][1] = "Create/modify all projects and tasks (also private projects I am not contact for). Can also enter time consumed on assigned tasks (timesheet)"; // libelle de la permission
+ $this->rights[$r][1] = "Create/modify all projects and tasks (also private projects I am not contact for)"; // libelle de la permission
$this->rights[$r][2] = 'w'; // type de la permission (deprecie a ce jour)
$this->rights[$r][3] = 0; // La permission est-elle une permission par defaut
$this->rights[$r][4] = 'all';
@@ -202,6 +202,12 @@ class modProjet extends DolibarrModules
$this->rights[$r][4] = 'all';
$this->rights[$r][5] = 'supprimer';
+ $r++;
+ $this->rights[$r][0] = 145; // id de la permission
+ $this->rights[$r][1] = "Can enter time consumed on assigned tasks (timesheet)"; // libelle de la permission
+ $this->rights[$r][2] = 'w'; // type de la permission (deprecie a ce jour)
+ $this->rights[$r][3] = 0; // La permission est-elle une permission par defaut
+ $this->rights[$r][4] = 'time';
// Menus
//-------
diff --git a/htdocs/core/modules/modRecruitment.class.php b/htdocs/core/modules/modRecruitment.class.php
index c4bbd573fa9..fb64e43486d 100644
--- a/htdocs/core/modules/modRecruitment.class.php
+++ b/htdocs/core/modules/modRecruitment.class.php
@@ -403,7 +403,7 @@ class modRecruitment extends DolibarrModules
{
global $conf, $langs;
- $result = $this->_load_tables('/install/mysql/tables/', 'recruitment');
+ $result = $this->_load_tables('/install/mysql/', 'recruitment');
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')
}
diff --git a/htdocs/core/modules/modStock.class.php b/htdocs/core/modules/modStock.class.php
index 839a62325f3..52a3843fd12 100644
--- a/htdocs/core/modules/modStock.class.php
+++ b/htdocs/core/modules/modStock.class.php
@@ -434,7 +434,7 @@ class modStock extends DolibarrModules
{
global $conf, $langs;
- $result = $this->_load_tables('/install/mysql/tables/', 'stock');
+ $result = $this->_load_tables('/install/mysql/', 'stock');
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')
}
diff --git a/htdocs/core/modules/modTicket.class.php b/htdocs/core/modules/modTicket.class.php
index 86a657c0509..688da3061d9 100644
--- a/htdocs/core/modules/modTicket.class.php
+++ b/htdocs/core/modules/modTicket.class.php
@@ -331,7 +331,7 @@ class modTicket extends DolibarrModules
{
global $conf, $langs;
- $result = $this->_load_tables('/install/mysql/tables/', 'ticket');
+ $result = $this->_load_tables('/install/mysql/', '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')
}
diff --git a/htdocs/core/modules/modWebsite.class.php b/htdocs/core/modules/modWebsite.class.php
index 7ea6b5a890c..e27e7a2f6b0 100644
--- a/htdocs/core/modules/modWebsite.class.php
+++ b/htdocs/core/modules/modWebsite.class.php
@@ -164,7 +164,7 @@ class modWebsite extends DolibarrModules
{
global $conf, $langs;
- $result = $this->_load_tables('/install/mysql/tables/', 'website');
+ $result = $this->_load_tables('/install/mysql/', 'website');
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')
}
diff --git a/htdocs/core/modules/modWorkstation.class.php b/htdocs/core/modules/modWorkstation.class.php
index 854dd45b969..80a401b4846 100644
--- a/htdocs/core/modules/modWorkstation.class.php
+++ b/htdocs/core/modules/modWorkstation.class.php
@@ -390,7 +390,7 @@ class modWorkstation extends DolibarrModules
{
global $conf, $langs;
- $result = $this->_load_tables('/install/mysql/tables/', 'workstation');
+ $result = $this->_load_tables('/install/mysql/', 'workstation');
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')
}
diff --git a/htdocs/core/modules/modZapier.class.php b/htdocs/core/modules/modZapier.class.php
index e638d906693..b6ef25e150e 100644
--- a/htdocs/core/modules/modZapier.class.php
+++ b/htdocs/core/modules/modZapier.class.php
@@ -281,7 +281,7 @@ class modZapier extends DolibarrModules
*/
public function init($options = '')
{
- $result = $this->_load_tables('/install/mysql/tables/', 'zapier');
+ $result = $this->_load_tables('/install/mysql/', 'zapier');
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')
}
diff --git a/htdocs/core/modules/propale/doc/pdf_azur.modules.php b/htdocs/core/modules/propale/doc/pdf_azur.modules.php
index 5135a1708af..c6bb975092d 100644
--- a/htdocs/core/modules/propale/doc/pdf_azur.modules.php
+++ b/htdocs/core/modules/propale/doc/pdf_azur.modules.php
@@ -964,6 +964,9 @@ class pdf_azur extends ModelePDFPropales
$pdf->SetXY($posxval, $posy);
$lib_condition_paiement = $outputlangs->transnoentities("PaymentCondition".$object->cond_reglement_code) != ('PaymentCondition'.$object->cond_reglement_code) ? $outputlangs->transnoentities("PaymentCondition".$object->cond_reglement_code) : $outputlangs->convToOutputCharset($object->cond_reglement_doc ? $object->cond_reglement_doc : $object->cond_reglement_label);
$lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
+ if ($object->deposit_percent > 0) {
+ $lib_condition_paiement = str_replace('__DEPOSIT_PERCENT__', $object->deposit_percent, $lib_condition_paiement);
+ }
$pdf->MultiCell(67, 4, $lib_condition_paiement, 0, 'L');
$posy = $pdf->GetY() + 3;
diff --git a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php
index 26ee429f97e..8651a9e720f 100644
--- a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php
+++ b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php
@@ -1083,6 +1083,9 @@ class pdf_cyan extends ModelePDFPropales
$pdf->SetXY($posxval, $posy);
$lib_condition_paiement = $outputlangs->transnoentities("PaymentCondition".$object->cond_reglement_code) != ('PaymentCondition'.$object->cond_reglement_code) ? $outputlangs->transnoentities("PaymentCondition".$object->cond_reglement_code) : $outputlangs->convToOutputCharset($object->cond_reglement_doc ? $object->cond_reglement_doc : $object->cond_reglement_label);
$lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
+ if ($object->deposit_percent > 0) {
+ $lib_condition_paiement = str_replace('__DEPOSIT_PERCENT__', $object->deposit_percent, $lib_condition_paiement);
+ }
$pdf->MultiCell(67, 4, $lib_condition_paiement, 0, 'L');
$posy = $pdf->GetY() + 3;
diff --git a/htdocs/core/tpl/massactions_pre.tpl.php b/htdocs/core/tpl/massactions_pre.tpl.php
index 4e138b0f1dc..207dc1b7265 100644
--- a/htdocs/core/tpl/massactions_pre.tpl.php
+++ b/htdocs/core/tpl/massactions_pre.tpl.php
@@ -211,6 +211,59 @@ if ($massaction == 'presend') {
print dol_get_fiche_end();
}
+if ($massaction == 'edit_extrafields') {
+ require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
+ $elementtype = $objecttmp->element;
+ /** @var CommonObject $objecttmp */
+ $extrafields = new ExtraFields($db);
+ $keysuffix = '';
+ $extrafields->fetch_name_optionals_label($elementtype);
+ $extrafields_list = $extrafields->attributes[$elementtype]['label'];
+
+ $formquestion = array();
+ if (!empty($extrafields_list)) {
+ $myParamExtra = $object->showOptionals($extrafields, 'create');
+
+ $formquestion[] = array(
+ 'type' => 'other',
+ 'value' => $form->selectarray('extrafield-key-to-update', $extrafields_list, GETPOST('extrafield-key-to-update'), 1)
+ );
+
+
+ $outputShowOutputFields = '
'.$langs->trans("SomeTranslationAreUncomplete").'';
// If there's no error, we display the next step button
if ($err == 0) {
diff --git a/htdocs/install/mysql/data/llx_c_partnership_type.sql b/htdocs/install/mysql/data/llx_c_partnership_type-partnership.sql
similarity index 100%
rename from htdocs/install/mysql/data/llx_c_partnership_type.sql
rename to htdocs/install/mysql/data/llx_c_partnership_type-partnership.sql
diff --git a/htdocs/install/mysql/data/llx_c_payment_term.sql b/htdocs/install/mysql/data/llx_c_payment_term.sql
index b5ff008912b..5a48e57a443 100644
--- a/htdocs/install/mysql/data/llx_c_payment_term.sql
+++ b/htdocs/install/mysql/data/llx_c_payment_term.sql
@@ -26,17 +26,18 @@
-- Do not include comments at end of line, this file is parsed during install and string '--' are removed.
--
-insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour) values (1 ,'RECEP', 1,1, 'Due upon receipt','Due upon receipt',0,1);
-insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour) values (2 ,'30D', 2,1, '30 days','Due in 30 days',0,30);
-insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour) values (3 ,'30DENDMONTH', 3,1, '30 days end of month','Due in 30 days, end of month',1,30);
-insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour) values (4 ,'60D', 4,1, '60 days','Due in 60 days, end of month',0,60);
-insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour) values (5 ,'60DENDMONTH', 5,1, '60 days end of month','Due in 60 days, end of month',1,60);
-insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour) values (6 ,'PT_ORDER', 6,1, 'Due on order','Due on order',0,1);
-insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour) values (7 ,'PT_DELIVERY', 7,1, 'Due on delivery','Due on delivery',0,1);
-insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour) values (8 ,'PT_5050', 8,1, '50 and 50','50% on order, 50% on delivery',0,1);
+insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour, deposit_percent) values (1 ,'RECEP', 1,1, 'Due upon receipt','Due upon receipt',0,1,NULL);
+insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour, deposit_percent) values (2 ,'30D', 2,1, '30 days','Due in 30 days',0,30,NULL);
+insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour, deposit_percent) values (3 ,'30DENDMONTH', 3,1, '30 days end of month','Due in 30 days, end of month',1,30,NULL);
+insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour, deposit_percent) values (4 ,'60D', 4,1, '60 days','Due in 60 days, end of month',0,60,NULL);
+insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour, deposit_percent) values (5 ,'60DENDMONTH', 5,1, '60 days end of month','Due in 60 days, end of month',1,60,NULL);
+insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour, deposit_percent) values (6 ,'PT_ORDER', 6,1, 'Due on order','Due on order',0,1,NULL);
+insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour, deposit_percent) values (7 ,'PT_DELIVERY', 7,1, 'Due on delivery','Due on delivery',0,1,NULL);
+insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour, deposit_percent) values (8 ,'PT_5050', 8,1, '50 and 50','50% on order, 50% on delivery',0,1,NULL);
-- Add additional payment terms often needed in Austria
-insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour) values (9 ,'10D', 9,1, '10 days','Due in 10 days',0,10);
-insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour) values (10,'10DENDMONTH', 10,1, '10 days end of month','Due in 10 days, end of month',1,10);
-insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour) values (11,'14D', 11,1, '14 days','Due in 14 days',0,14);
-insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour) values (12,'14DENDMONTH', 12,1, '14 days end of month','Due in 14 days, end of month',1,14);
+insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour, deposit_percent) values (9 ,'10D', 9,1, '10 days','Due in 10 days',0,10,NULL);
+insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour, deposit_percent) values (10,'10DENDMONTH', 10,1, '10 days end of month','Due in 10 days, end of month',1,10,NULL);
+insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour, deposit_percent) values (11,'14D', 11,1, '14 days','Due in 14 days',0,14,NULL);
+insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour, deposit_percent) values (12,'14DENDMONTH', 12,1, '14 days end of month','Due in 14 days, end of month',1,14,NULL);
+insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour, deposit_percent) values (13,'DEP30PCTDEL', 13,0, '__DEPOSIT_PERCENT__% deposit','__DEPOSIT_PERCENT__% deposit, remainder on delivery',0,1,'30');
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 bef32bc7fe7..7355f1d8987 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
@@ -538,6 +538,18 @@ INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (154,
-- VMYSQL4.3 ALTER TABLE llx_user MODIFY COLUMN fk_soc integer NULL;
-- VPGSQL8.2 ALTER TABLE llx_user ALTER COLUMN fk_soc DROP NOT NULL;
+CREATE TABLE llx_element_tag
+(
+ rowid integer AUTO_INCREMENT PRIMARY KEY,
+ fk_categorie integer NOT NULL,
+ fk_element integer NOT NULL,
+ import_key varchar(14)
+)ENGINE=innodb;
+
+ALTER TABLE llx_element_tag ADD UNIQUE INDEX idx_element_tag_uk (fk_categorie, fk_element);
+
+ALTER TABLE llx_element_tag ADD CONSTRAINT fk_element_tag_categorie_rowid FOREIGN KEY (fk_categorie) REFERENCES llx_categorie (rowid);
+
-- Add column to help to fix a very critical bug when transferring into accounting bank record of a bank account into another currency.
-- Idea is to update this column manually in v15 with value in currency of company for bank that are not into the main currency and the transfer
-- into accounting will use it in priority if value is not null. The script repair.sql contains the sequence to fix datas in llx_bank.
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 186a789cac9..5ff0d82a0d0 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
@@ -105,6 +105,8 @@ ALTER TABLE llx_bank ADD COLUMN amount_main_currency double(24,8) NULL;
-- v16
+ALTER TABLE llx_societe_account DROP FOREIGN KEY llx_societe_account_fk_website;
+
UPDATE llx_cronjob set label = 'RecurringInvoicesJob' where label = 'RecurringInvoices';
UPDATE llx_cronjob set label = 'RecurringSupplierInvoicesJob' where label = 'RecurringSupplierInvoices';
@@ -325,6 +327,15 @@ UPDATE llx_c_availability SET type_duration = 'w', qty = 2 WHERE code = 'AV_2W';
UPDATE llx_c_availability SET type_duration = 'w', qty = 3 WHERE code = 'AV_3W';
UPDATE llx_c_availability SET type_duration = 'w', qty = 4 WHERE code = 'AV_4W';
+
+-- Deposit generation helper with specific payment terms
+ALTER TABLE llx_c_payment_term ADD COLUMN deposit_percent VARCHAR(63) DEFAULT NULL AFTER decalage;
+ALTER TABLE llx_societe ADD COLUMN deposit_percent VARCHAR(63) DEFAULT NULL AFTER cond_reglement;
+ALTER TABLE llx_propal ADD COLUMN deposit_percent VARCHAR(63) DEFAULT NULL AFTER fk_cond_reglement;
+ALTER TABLE llx_commande ADD COLUMN deposit_percent VARCHAR(63) DEFAULT NULL AFTER fk_cond_reglement;
+INSERT INTO llx_c_payment_term(code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour, deposit_percent) values ('DEP30PCTDEL', 13, 0, '__DEPOSIT_PERCENT__% deposit', '__DEPOSIT_PERCENT__% deposit, remainder on delivery', 0, 1, '30');
+
+
ALTER TABLE llx_boxes_def ADD COLUMN fk_user integer DEFAULT 0 NOT NULL;
ALTER TABLE llx_contratdet ADD COLUMN rang integer DEFAULT 0 AFTER info_bits;
@@ -339,8 +350,14 @@ ALTER TABLE llx_takepos_floor_tables ADD UNIQUE(entity,label);
ALTER TABLE llx_partnership ADD COLUMN url_to_check varchar(255);
ALTER TABLE llx_c_partnership_type ADD COLUMN keyword varchar(128);
+
ALTER TABLE llx_eventorganization_conferenceorboothattendee ADD COLUMN firstname varchar(100);
ALTER TABLE llx_eventorganization_conferenceorboothattendee ADD COLUMN lastname varchar(100);
ALTER TABLE llx_eventorganization_conferenceorboothattendee ADD COLUMN email_company varchar(128) after email;
-ALTER TABLE llx_inventory ADD COLUMN fk_categories_product VARCHAR(255) DEFAULT NULL AFTER fk_product;
+ALTER TABLE llx_inventory ADD COLUMN categories_product VARCHAR(255) DEFAULT NULL AFTER fk_product;
+
+ALTER TABLE llx_c_email_template ADD COLUMN email_from varchar(255);
+ALTER TABLE llx_c_email_template ADD COLUMN email_to varchar(255);
+ALTER TABLE llx_c_email_template ADD COLUMN email_tocc varchar(255);
+ALTER TABLE llx_c_email_template ADD COLUMN email_tobcc varchar(255);
diff --git a/htdocs/install/mysql/tables/llx_c_email_templates.sql b/htdocs/install/mysql/tables/llx_c_email_templates.sql
index 04130a208fe..4d22767bc58 100644
--- a/htdocs/install/mysql/tables/llx_c_email_templates.sql
+++ b/htdocs/install/mysql/tables/llx_c_email_templates.sql
@@ -32,6 +32,10 @@ create table llx_c_email_templates
position smallint, -- Position
enabled varchar(255) DEFAULT '1', -- Condition to have this module visible
active tinyint DEFAULT 1 NOT NULL,
+ email_from varchar(255), -- default email from
+ email_to varchar(255), -- default email to
+ email_tocc varchar(255), -- default email to cc
+ email_tobcc varchar(255), -- default email to bcc
topic text, -- Predefined topic
joinfiles text, -- Files to attach
content mediumtext, -- Predefined text
diff --git a/htdocs/install/mysql/tables/llx_c_payment_term.sql b/htdocs/install/mysql/tables/llx_c_payment_term.sql
index 087ab63c184..e7b2b606b65 100644
--- a/htdocs/install/mysql/tables/llx_c_payment_term.sql
+++ b/htdocs/install/mysql/tables/llx_c_payment_term.sql
@@ -30,6 +30,7 @@ create table llx_c_payment_term
type_cdr tinyint, -- Type of change date reckoning. 1=Payment at end of current month, 2=the Nth of next month
nbjour smallint,
decalage smallint,
+ deposit_percent varchar(63) DEFAULT NULL,
module varchar(32) NULL,
position integer NOT NULL DEFAULT 0
)ENGINE=innodb;
diff --git a/htdocs/install/mysql/tables/llx_commande.sql b/htdocs/install/mysql/tables/llx_commande.sql
index 5b8a78c7bf8..94b1f38227d 100644
--- a/htdocs/install/mysql/tables/llx_commande.sql
+++ b/htdocs/install/mysql/tables/llx_commande.sql
@@ -63,6 +63,7 @@ create table llx_commande
fk_account integer, -- bank account
fk_currency varchar(3), -- currency code
fk_cond_reglement integer, -- condition de reglement
+ deposit_percent varchar(63) DEFAULT NULL, -- default deposit % if payment term needs it
fk_mode_reglement integer, -- mode de reglement
date_livraison datetime default NULL,
diff --git a/htdocs/install/mysql/tables/llx_inventory-stock.sql b/htdocs/install/mysql/tables/llx_inventory-stock.sql
index 7df2f72534a..0c7a6d2eb49 100644
--- a/htdocs/install/mysql/tables/llx_inventory-stock.sql
+++ b/htdocs/install/mysql/tables/llx_inventory-stock.sql
@@ -29,7 +29,7 @@ CREATE TABLE llx_inventory
fk_user_valid integer, -- valideur de la fiche
fk_warehouse integer DEFAULT NULL,
fk_product integer DEFAULT NULL,
- fk_categories_product varchar(255) DEFAULT NULL, -- product categories id separated by comma
+ categories_product varchar(255) DEFAULT NULL, -- product categories id separated by comma
status integer DEFAULT 0,
title varchar(255) NOT NULL,
date_inventory datetime DEFAULT NULL,
diff --git a/htdocs/install/mysql/tables/llx_product.sql b/htdocs/install/mysql/tables/llx_product.sql
index 80e3f90b828..83e8882caa7 100644
--- a/htdocs/install/mysql/tables/llx_product.sql
+++ b/htdocs/install/mysql/tables/llx_product.sql
@@ -40,8 +40,8 @@ create table llx_product
customcode varchar(32), -- Optionnal custom code
fk_country integer DEFAULT NULL, -- Optionnal id of original country
fk_state integer DEFAULT NULL, -- Optionnal id of original state/province
- price double(24,8) DEFAULT 0,
- price_ttc double(24,8) DEFAULT 0,
+ price double(24,8) DEFAULT 0, -- price without tax
+ price_ttc double(24,8) DEFAULT 0, -- price inc vat (but not localtax1 nor localtax2)
price_min double(24,8) DEFAULT 0,
price_min_ttc double(24,8) DEFAULT 0,
price_base_type varchar(3) DEFAULT 'HT',
diff --git a/htdocs/install/mysql/tables/llx_product_price.sql b/htdocs/install/mysql/tables/llx_product_price.sql
index 77a00939428..2a64fc92c30 100644
--- a/htdocs/install/mysql/tables/llx_product_price.sql
+++ b/htdocs/install/mysql/tables/llx_product_price.sql
@@ -29,8 +29,8 @@ create table llx_product_price
fk_product integer NOT NULL,
date_price datetime NOT NULL,
price_level smallint NULL DEFAULT 1,
- price double(24,8) DEFAULT NULL,
- price_ttc double(24,8) DEFAULT NULL,
+ price double(24,8) DEFAULT NULL, -- price without tax
+ price_ttc double(24,8) DEFAULT NULL, -- price inc vat (but not localtax1 nor localtax2)
price_min double(24,8) default NULL,
price_min_ttc double(24,8) default NULL,
price_base_type varchar(3) DEFAULT 'HT',
diff --git a/htdocs/install/mysql/tables/llx_propal.sql b/htdocs/install/mysql/tables/llx_propal.sql
index 3499a51e8b8..a8f0aa3e2c9 100644
--- a/htdocs/install/mysql/tables/llx_propal.sql
+++ b/htdocs/install/mysql/tables/llx_propal.sql
@@ -58,6 +58,7 @@ create table llx_propal
fk_account integer, -- bank account
fk_currency varchar(3), -- currency code
fk_cond_reglement integer, -- condition de reglement (30 jours, fin de mois ...)
+ deposit_percent varchar(63) DEFAULT NULL, -- default deposit % if payment term needs it
fk_mode_reglement integer, -- mode de reglement (Virement, Prelevement)
online_sign_ip varchar(48),
diff --git a/htdocs/install/mysql/tables/llx_societe.sql b/htdocs/install/mysql/tables/llx_societe.sql
index c27a0fb2910..3c2f8a67be1 100644
--- a/htdocs/install/mysql/tables/llx_societe.sql
+++ b/htdocs/install/mysql/tables/llx_societe.sql
@@ -52,15 +52,6 @@ create table llx_societe
email varchar(128), --
socialnetworks text DEFAULT NULL, -- json with socialnetworks
- --skype varchar(255), -- deprecated
- --twitter varchar(255), -- deprecated
- --facebook varchar(255), -- deprecated
- --linkedin varchar(255), -- deprecated
- --instagram varchar(255), -- deprecated
- --snapchat varchar(255), -- deprecated
- --googleplus varchar(255), -- deprecated
- --youtube varchar(255), -- deprecated
- --whatsapp varchar(255), -- deprecated
fk_effectif integer DEFAULT 0, --
fk_typent integer DEFAULT NULL, -- type ent
@@ -93,6 +84,7 @@ create table llx_societe
remise_supplier real DEFAULT 0, -- discount by default granted by this supplier
mode_reglement tinyint, -- payment mode customer
cond_reglement tinyint, -- payment term customer
+ deposit_percent varchar(63) DEFAULT NULL, -- default deposit % if payment term needs it
transport_mode tinyint, -- transport mode customer (Intracomm report)
mode_reglement_supplier tinyint, -- payment mode supplier
cond_reglement_supplier tinyint, -- payment term supplier
diff --git a/htdocs/install/mysql/tables/llx_societe_account.key.sql b/htdocs/install/mysql/tables/llx_societe_account.key.sql
index e86c12aa306..e889a38d527 100644
--- a/htdocs/install/mysql/tables/llx_societe_account.key.sql
+++ b/htdocs/install/mysql/tables/llx_societe_account.key.sql
@@ -25,6 +25,8 @@ ALTER TABLE llx_societe_account ADD INDEX idx_societe_account_fk_soc (fk_soc);
ALTER TABLE llx_societe_account ADD UNIQUE INDEX uk_societe_account_login_website_soc(entity, fk_soc, login, site, fk_website);
ALTER TABLE llx_societe_account ADD UNIQUE INDEX uk_societe_account_key_account_soc(entity, fk_soc, key_account, site, fk_website);
-ALTER TABLE llx_societe_account ADD CONSTRAINT llx_societe_account_fk_website FOREIGN KEY (fk_website) REFERENCES llx_website(rowid);
+-- Table website does not always exists
+--ALTER TABLE llx_societe_account ADD CONSTRAINT llx_societe_account_fk_website FOREIGN KEY (fk_website) REFERENCES llx_website(rowid);
+
ALTER TABLE llx_societe_account ADD CONSTRAINT llx_societe_account_fk_societe FOREIGN KEY (fk_soc) REFERENCES llx_societe(rowid);
diff --git a/htdocs/install/pgsql/functions/functions-don.sql b/htdocs/install/pgsql/functions/functions-don.sql
new file mode 100644
index 00000000000..a1a51b57e6d
--- /dev/null
+++ b/htdocs/install/pgsql/functions/functions-don.sql
@@ -0,0 +1,20 @@
+-- ============================================================================
+-- Copyright (C) 2010 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 .
+--
+-- ============================================================================
+
+CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_don FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
+CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_don_extrafields FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
diff --git a/htdocs/install/pgsql/functions/functions-loan.sql b/htdocs/install/pgsql/functions/functions-loan.sql
new file mode 100644
index 00000000000..d63e394e5c9
--- /dev/null
+++ b/htdocs/install/pgsql/functions/functions-loan.sql
@@ -0,0 +1,19 @@
+-- ============================================================================
+-- Copyright (C) 2010 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 .
+--
+-- ============================================================================
+
+CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_loan FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
diff --git a/htdocs/install/pgsql/functions/functions-mailing.sql b/htdocs/install/pgsql/functions/functions-mailing.sql
new file mode 100644
index 00000000000..d45d620399f
--- /dev/null
+++ b/htdocs/install/pgsql/functions/functions-mailing.sql
@@ -0,0 +1,20 @@
+-- ============================================================================
+-- Copyright (C) 2010 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 .
+--
+-- ============================================================================
+
+CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_mailing FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
+CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_mailing_cibles FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
diff --git a/htdocs/install/pgsql/functions/functions-opensurvey.sql b/htdocs/install/pgsql/functions/functions-opensurvey.sql
new file mode 100644
index 00000000000..d42a8311cb2
--- /dev/null
+++ b/htdocs/install/pgsql/functions/functions-opensurvey.sql
@@ -0,0 +1,21 @@
+-- ============================================================================
+-- Copyright (C) 2010 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 .
+--
+-- ============================================================================
+
+CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_opensurvey_comments FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
+CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_opensurvey_sondage FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
+CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_opensurvey_user_studs FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
diff --git a/htdocs/install/pgsql/functions/functions-partnership.sql b/htdocs/install/pgsql/functions/functions-partnership.sql
new file mode 100644
index 00000000000..61e991e1197
--- /dev/null
+++ b/htdocs/install/pgsql/functions/functions-partnership.sql
@@ -0,0 +1,20 @@
+-- ============================================================================
+-- Copyright (C) 2010 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 .
+--
+-- ============================================================================
+
+CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_partnership FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
+CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_partnership_extrafields FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
diff --git a/htdocs/install/pgsql/functions/functions-recruitment.sql b/htdocs/install/pgsql/functions/functions-recruitment.sql
new file mode 100644
index 00000000000..9fa6023be1a
--- /dev/null
+++ b/htdocs/install/pgsql/functions/functions-recruitment.sql
@@ -0,0 +1,23 @@
+-- ============================================================================
+-- Copyright (C) 2010 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 .
+--
+-- ============================================================================
+
+CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_recruitment_recruitmentjobposition FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
+CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_recruitment_recruitmentjobposition_extrafields FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
+CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_recruitment_recruitmentcandidature FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
+CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_recruitment_recruitmentcandidature_extrafields FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
+
diff --git a/htdocs/install/pgsql/functions/functions-website.sql b/htdocs/install/pgsql/functions/functions-website.sql
new file mode 100644
index 00000000000..a5597837466
--- /dev/null
+++ b/htdocs/install/pgsql/functions/functions-website.sql
@@ -0,0 +1,21 @@
+-- ============================================================================
+-- Copyright (C) 2010 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 .
+--
+-- ============================================================================
+
+CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_website FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
+CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_website_page FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
+
diff --git a/htdocs/install/pgsql/functions/functions.sql b/htdocs/install/pgsql/functions/functions.sql
index d73678bcbab..35bc4e05c11 100644
--- a/htdocs/install/pgsql/functions/functions.sql
+++ b/htdocs/install/pgsql/functions/functions.sql
@@ -100,9 +100,6 @@ CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_contratdet_extrafiel
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_contratdet_log FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_subscription FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_cronjob FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
-CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_deplacement FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
-CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_don FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
-CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_don_extrafields FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_ecm_directories FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_ecm_files FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_element_resources FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
@@ -126,19 +123,13 @@ CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_fichinter FOR EACH R
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_fichinter_extrafields FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_fichinterdet_extrafields FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_delivery FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
-CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_loan FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_localtax FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
-CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_mailing FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
-CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_mailing_cibles FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_menu FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_mrp_mo FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_mrp_mo_extrafields FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_mrp_production FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_notify FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_notify_def FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
-CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_opensurvey_comments FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
-CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_opensurvey_sondage FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
-CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_opensurvey_user_studs FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_paiement FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_paiementcharge FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_paiementfourn FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
@@ -165,10 +156,6 @@ CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_propal_extrafields F
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_propal_merge_pdf_product FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_propaldet_extrafields FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_resource FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
-CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_recruitment_recruitmentjobposition FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
-CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_recruitment_recruitmentjobposition_extrafields FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
-CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_recruitment_recruitmentcandidature FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
-CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_recruitment_recruitmentcandidature_extrafields FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_salary FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_societe FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_societe_address FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
@@ -187,5 +174,3 @@ CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_user FOR EACH ROW EX
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_user_extrafields FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_usergroup FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_usergroup_extrafields FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
-CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_website FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
-CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_website_page FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms();
diff --git a/htdocs/install/step1.php b/htdocs/install/step1.php
index 63b8d66539b..9613e1a86b5 100644
--- a/htdocs/install/step1.php
+++ b/htdocs/install/step1.php
@@ -261,6 +261,7 @@ if (!$error) {
$error++;
}
}
+
// If we need simple access
if (!$error && (empty($db_create_database) && empty($db_create_user))) {
$db = getDoliDBInstance($db_type, $db_host, $db_user, $db_pass, $db_name, $db_port);
diff --git a/htdocs/install/step4.php b/htdocs/install/step4.php
index e1890656f4b..c8be975c19f 100644
--- a/htdocs/install/step4.php
+++ b/htdocs/install/step4.php
@@ -82,9 +82,9 @@ if ($db->ok) {
print '
';
}
if ($object->status == $object::STATUS_DRAFT || $object->status == $object::STATUS_VALIDATED) {
// Actions or link to stock movement
@@ -1020,7 +1023,13 @@ if ($object->id > 0) {
if (!empty($conf->productbatch->enabled)) {
print '
';
@@ -2199,7 +2267,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
$pu = $object->price_ttc;
}
- // Local tax is not saved into table of product. We use value linked to VAT code.
+ // Local tax was not saved into table llx_product on old version. So we will use value linked to VAT code.
$localtaxarray = getLocalTaxesFromRate($object->tva_tx.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), 0, $mysoc, $mysoc);
// Define part of HT, VAT, TTC
$resultarray = calcul_price_total(1, $pu, 0, $object->tva_tx, 1, 1, 0, $object->price_base_type, $object->recuperableonly, $object->type, $mysoc, $localtaxarray);
@@ -2237,14 +2305,12 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
print '
';
$constforvar = 'RECRUITMENT_'.strtoupper($myTmpObjectKey).'_ADDON_PDF';
- if ($conf->global->$constforvar == $name) {
+ if (getDolGlobalString($constforvar) == $name) {
//print img_picto($langs->trans("Default"), 'on');
// Even if choice is the default value, we allow to disable it. Replace this with previous line if you need to disable unset
print 'scandir).'&label='.urlencode($module->name).'&type='.urlencode($type).'" alt="'.$langs->trans("Disable").'">'.img_picto($langs->trans("Enabled"), 'on').'';
diff --git a/htdocs/recruitment/admin/setup_candidatures.php b/htdocs/recruitment/admin/setup_candidatures.php
index 726e24e89b1..58172c2e767 100644
--- a/htdocs/recruitment/admin/setup_candidatures.php
+++ b/htdocs/recruitment/admin/setup_candidatures.php
@@ -328,7 +328,7 @@ foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) {
print '
';
$constforvar = 'RECRUITMENT_'.strtoupper($myTmpObjectKey).'_ADDON';
- if ($conf->global->$constforvar == $name) {
+ if (getDolGlobalString($constforvar) == $name) {
//print img_picto($langs->trans("Default"), 'on');
// Even if choice is the default value, we allow to disable it. Replace this with previous line if you need to disable unset
print 'scandir).'&label='.urlencode($module->name).'&type='.urlencode($type).'" alt="'.$langs->trans("Disable").'">'.img_picto($langs->trans("Enabled"), 'on').'';
diff --git a/htdocs/recruitment/core/modules/recruitment/doc/doc_generic_recruitmentjobposition_odt.modules.php b/htdocs/recruitment/core/modules/recruitment/doc/doc_generic_recruitmentjobposition_odt.modules.php
index e2b7c545aa9..c28bd4a9589 100644
--- a/htdocs/recruitment/core/modules/recruitment/doc/doc_generic_recruitmentjobposition_odt.modules.php
+++ b/htdocs/recruitment/core/modules/recruitment/doc/doc_generic_recruitmentjobposition_odt.modules.php
@@ -130,7 +130,7 @@ class doc_generic_recruitmentjobposition_odt extends ModelePDFRecruitmentJobPosi
// List of directories area
$texte .= '
';
+
+// complete header by hook
+$parameters=array();
+$reshook=$hookmanager->executeHooks('completeTakePosInvoiceHeader', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
+if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
+print $hookmanager->resPrint;
+
if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
print '
'.$langs->trans('ReductionShort').'
';
print '
'.$langs->trans('Qty').'
';
@@ -1445,6 +1452,13 @@ if ($placeid > 0) {
}
}
$htmlsupplements[$line->fk_parent_line] .= '';
+
+ // complete line by hook
+ $parameters=array('line' => $line);
+ $reshook=$hookmanager->executeHooks('completeTakePosInvoiceParentLine', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
+ $htmlsupplements[$line->fk_parent_line] .= $hookmanager->resPrint;
+
if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
$htmlsupplements[$line->fk_parent_line] .= '
';
}
$htmlforlines .= '';
+
+ // complete line by hook
+ $parameters=array('line' => $line);
+ $reshook=$hookmanager->executeHooks('completeTakePosInvoiceLine', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
+ $htmlforlines .= $hookmanager->resPrint;
+
$htmlforlines .= '
'.vatrate($line->remise_percent, true).'
';
$htmlforlines .= '
';
if (!empty($conf->stock->enabled) && !empty($user->rights->stock->mouvement->lire)) {
diff --git a/htdocs/theme/eldy/btn.inc.php b/htdocs/theme/eldy/btn.inc.php
index 45ed3889a13..b29c55bd02d 100644
--- a/htdocs/theme/eldy/btn.inc.php
+++ b/htdocs/theme/eldy/btn.inc.php
@@ -147,9 +147,9 @@ span.butActionNewRefused>span.fa, span.butActionNewRefused>span.fa:hover
}
.butActionDelete, .butActionDelete:link, .butActionDelete:visited, .butActionDelete:hover, .butActionDelete:active, .buttonDelete {
- background: var(--butactiondeletebg);
+ background: var(--butactiondeletebg) !important;
/* border: 1px solid #633; */
- color: #633;
+ color: #633 !important;
}
.butActionDelete:hover {
diff --git a/htdocs/theme/eldy/dropdown.inc.php b/htdocs/theme/eldy/dropdown.inc.php
index 6ca9ad67b1f..338b4cf2759 100644
--- a/htdocs/theme/eldy/dropdown.inc.php
+++ b/htdocs/theme/eldy/dropdown.inc.php
@@ -121,8 +121,17 @@ button.dropdown-item.global-search-item {
text-decoration: none !important;
}
+
+/* CSS to hide the arrow to show open/close */
+div#topmenu-quickadd-dropdown, div#topmenu-bookmark-dropdown {
+ padding-right: 5px;
+}
+div#topmenu-quickadd-dropdown a::after, div#topmenu-bookmark-dropdown a::after {
+ display: none;
+}
+
+
.dropdown-toggle::after {
- /* font part */
font-family: "Font Awesome 5 Free";
font-size: 0.7em;
font-weight: 900;
@@ -141,6 +150,7 @@ button.dropdown-item.global-search-item {
transition: transform .2s ease-in-out;
}
+
.open>.dropdown-toggle::after {
transform: rotate(180deg);
}
diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php
index ff6fe3c4fb8..db827600b33 100644
--- a/htdocs/theme/eldy/global.inc.php
+++ b/htdocs/theme/eldy/global.inc.php
@@ -240,7 +240,7 @@ input, select {
}
#mainbody input.button:not(.buttongen):not(.bordertransp), #mainbody a.button:not(.buttongen):not(.bordertransp) {
background: var(--butactionbg);
- color: var(--textbutaction)!important;
+ color: var(--textbutaction);
border-radius: 3px;
border-collapse: collapse;
border: none;
@@ -2605,27 +2605,45 @@ a.tmenuimage:hover{
/* To show text of top menu on hover only (THEME_TOPMENU_DISABLE_IMAGE == 2) */
-.tmenulabel:not(.menuhider), .tmenulabel:not(.menuhider):before {
- display: none;
+.tmenulabel:not(.menuhider), .tmenulabel:not(.menuhider)::before {
+ display: none;
+ /* opacity: 0; To show text after transition */
}
-a.tmenuimage:not(.menuhider), a.tmenuimage:not(.menuhider):before,
-div.tmenuimage:not(.menuhider), div.tmenuimage:not(.menuhider):before,
-span.tmenuimage:not(.menuhider), span.tmenuimage:not(.menuhider):before {
+a.tmenuimage:not(.menuhider), a.tmenuimage:not(.menuhider)::before,
+div.tmenuimage:not(.menuhider), div.tmenuimage:not(.menuhider)::before,
+span.tmenuimage:not(.menuhider), span.tmenuimage:not(.menuhider)::before {
font-size: 1.3em;
- margin-top: 10px !important;
+ margin-top: 8px !important;
}
+
-.tmenudiv:hover .tmenulabel:not(.menuhider), .tmenudiv:hover .tmenulabel:not(.menuhider):before {
+.tmenudiv:hover .tmenulabel:not(.menuhider), .tmenudiv:hover .tmenulabel:not(.menuhider)::before {
+ display: block;
+ position: relative;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ /* For transition transition-delay: 1000ms;
+ transition-property: all; */
+ opacity: 1;
display: initial !important;
+ line-height: 0.6em !important;
+ height: 1em !important;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ color: var(--colortextbackhmenu);
+ top: 0px;
}
-.tmenudiv:hover .tmenuimage:not(.menuhider), .tmenudiv:hover .tmenuimage:not(.menuhider):before {
- font-size: 1.1em !important;
+
+.tmenudiv:hover .tmenuimage:not(.menuhider), .tmenudiv:hover .tmenuimage:not(.menuhider)::before {
+ /* For transition transition-delay: 1000ms;
+ transition-property: all; */
margin-top: 0px !important;
}
+
-li.tmenu:hover .tmenulabel:not(.menuhider), li.tmenu:hover .tmenulabel:not(.menuhider):before {
+li.tmenu:hover .tmenulabel:not(.menuhider), li.tmenu:hover .tmenulabel:not(.menuhider)::before {
display: initial !important;
}
li.tmenu:hover .tmenuimage:not(.menuhider), li.tmenu:hover .tmenuimage:not(.menuhider):before {
@@ -2694,12 +2712,14 @@ li.tmenu:hover .tmenuimage:not(.menuhider), li.tmenu:hover .tmenuimage:not(.menu
$url = dol_buildpath($path.'/theme/'.$theme.'/img/menus/generic'.(min($generic, 4))."_over.png", 1);
print "div.mainmenu.".$val." {\n";
print " background-image: url(".$url.");\n";
+ print " background-position-y: 3px;\n";
print "}\n";
}
$generic++;
} else {
print "div.mainmenu.".$val." {\n";
print " background-image: url(".$url.");\n";
+ print " background-position-y: 3px;\n";
print "}\n";
}
}
@@ -3811,12 +3831,6 @@ div.pagination {
div.pagination a {
font-weight: normal;
}
-/*div.pagination a.butAction, div.fichehalfright a.butAction {
- margin-right: 0px !important;
-}
-div.tabsAction a.butActionDelete:last-child, div.tabsAction a.butAction:last-child {
- margin-right: 0px !important;
-}*/
div.pagination ul
{
list-style: none;
@@ -7327,11 +7341,18 @@ div.clipboardCPValue.hidewithsize {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
+
color: var(--colortextbackhmenu);
+ /* color: var(--colorbackhmenu1); */
}
+ .tmenuimage {
+ color: var(--colortextbackhmenu);
+ }
+
.mainmenuaspan {
font-size: 0.9em;
padding-right: 0;
+ padding-left: 0;
}
.topmenuimage {
background-size: 22px auto;
@@ -7386,6 +7407,15 @@ div.clipboardCPValue.hidewithsize {
/* rule to reduce top menu - 3rd reduction: The menu for user is on left */
@media only screen and (max-width: global->THEME_ELDY_WITDHOFFSET_FOR_REDUC3) ? round($nbtopmenuentries * 47, 0) + 130 : $conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC3; ?>px) /* reduction 3 */
{
+
+ .tmenudiv .tmenulabel span.mainmenuaspan {
+ display: none !important;
+ }
+ .tmenudiv:hover .tmenuimage:not(.menuhider), .tmenudiv:hover .tmenuimage:not(.menuhider):before {
+ margin-top: 8px !important;
+ }
+
+
.side-nav {
z-index: 200;
background: var(--colorbackvmenu1);
diff --git a/htdocs/theme/eldy/main_menu_fa_icons.inc.php b/htdocs/theme/eldy/main_menu_fa_icons.inc.php
index 60c3746fe66..ada1ae23a12 100644
--- a/htdocs/theme/eldy/main_menu_fa_icons.inc.php
+++ b/htdocs/theme/eldy/main_menu_fa_icons.inc.php
@@ -10,12 +10,12 @@
font-style: normal;
font-variant: normal;
text-rendering: auto;
- line-height: 23px;
- font-size: ;
+ line-height: 28px;
-webkit-font-smoothing: antialiased;
text-align:center;
text-decoration:none;
color: var(--colortextbackhmenu);
+ /* font-size: ; */
}
.fa-15x {
diff --git a/htdocs/theme/md/dropdown.inc.php b/htdocs/theme/md/dropdown.inc.php
index c56590d7bfa..615951bbbd9 100644
--- a/htdocs/theme/md/dropdown.inc.php
+++ b/htdocs/theme/md/dropdown.inc.php
@@ -26,7 +26,7 @@ button.dropdown-item.global-search-item {
}
div#topmenu-quickadd-dropdown {
position: fixed;
- : 65px;
+ : 55px;
top: 0px;
}
div#topmenu-bookmark-dropdown {
@@ -124,6 +124,15 @@ button.dropdown-item.global-search-item {
}
+/* CSS to hide the arrow to show open/close */
+div#topmenu-quickadd-dropdown, div#topmenu-bookmark-dropdown {
+ padding-right: 2px;
+}
+div#topmenu-quickadd-dropdown a::after, div#topmenu-bookmark-dropdown a::after {
+ display: none;
+}
+
+
.dropdown-toggle{
text-decoration: none !important;
}
diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php
index 9e50dd2c47d..33ca6d0ec9c 100644
--- a/htdocs/user/class/user.class.php
+++ b/htdocs/user/class/user.class.php
@@ -297,7 +297,7 @@ class User extends CommonObject
public $all_permissions_are_loaded;
/**
- * @var int Number of rights granted to the user
+ * @var int Number of rights granted to the user. Value loaded after a getrights().
*/
public $nb_rights;
@@ -883,15 +883,18 @@ class User extends CommonObject
$i = 0;
while ($i < $num) {
$obj = $this->db->fetch_object($result);
- $nid = $obj->id;
- $sql = "DELETE FROM ".$this->db->prefix()."user_rights WHERE fk_user = ".((int) $this->id)." AND fk_id = ".((int) $nid)." AND entity = ".((int) $entity);
- if (!$this->db->query($sql)) {
- $error++;
- }
- $sql = "INSERT INTO ".$this->db->prefix()."user_rights (entity, fk_user, fk_id) VALUES (".((int) $entity).", ".((int) $this->id).", ".((int) $nid).")";
- if (!$this->db->query($sql)) {
- $error++;
+ if ($obj) {
+ $nid = $obj->id;
+
+ $sql = "DELETE FROM ".$this->db->prefix()."user_rights WHERE fk_user = ".((int) $this->id)." AND fk_id = ".((int) $nid)." AND entity = ".((int) $entity);
+ if (!$this->db->query($sql)) {
+ $error++;
+ }
+ $sql = "INSERT INTO ".$this->db->prefix()."user_rights (entity, fk_user, fk_id) VALUES (".((int) $entity).", ".((int) $this->id).", ".((int) $nid).")";
+ if (!$this->db->query($sql)) {
+ $error++;
+ }
}
$i++;
@@ -1096,6 +1099,14 @@ class User extends CommonObject
}
}
+ // For avoid error
+ if (!isset($this->rights) || !is_object($this->rights)) {
+ $this->rights = new stdClass(); // For avoid error
+ }
+ if (!isset($this->rights->user) || !is_object($this->rights->user)) {
+ $this->rights->user = new stdClass(); // For avoid error
+ }
+
// Get permission of users + Get permissions of groups
// First user permissions
@@ -1121,7 +1132,6 @@ class User extends CommonObject
if ($resql) {
$num = $this->db->num_rows($resql);
$i = 0;
-
while ($i < $num) {
$obj = $this->db->fetch_object($resql);
@@ -1131,9 +1141,6 @@ class User extends CommonObject
$subperms = $obj->subperms;
if (!empty($perms)) {
- if (!isset($this->rights) || !is_object($this->rights)) {
- $this->rights = new stdClass(); // For avoid error
- }
if (!empty($module)) {
if (!isset($this->rights->$module) || !is_object($this->rights->$module)) {
$this->rights->$module = new stdClass();
@@ -1200,9 +1207,6 @@ class User extends CommonObject
$subperms = $obj->subperms;
if (!empty($perms)) {
- if (!isset($this->rights) || !is_object($this->rights)) {
- $this->rights = new stdClass(); // For avoid error
- }
if (!empty($module)) {
if (!isset($this->rights->$module) || !is_object($this->rights->$module)) {
$this->rights->$module = new stdClass();
@@ -1232,6 +1236,63 @@ class User extends CommonObject
$this->db->free($resql);
}
+ // Force permission on user for admin
+ if (!empty($this->admin)) {
+ if (empty($this->rights->user->user)) {
+ $this->rights->user->user = new stdClass();
+ }
+ $listofpermtotest = array('lire', 'creer', 'password', 'supprimer', 'export');
+ foreach ($listofpermtotest as $permtotest) {
+ if (empty($this->rights->user->user->$permtotest)) {
+ $this->rights->user->user->$permtotest = 1;
+ $this->nb_rights++;
+ }
+ }
+ if (empty($this->rights->user->self)) {
+ $this->rights->user->self = new stdClass();
+ }
+ $listofpermtotest = array('creer', 'password');
+ foreach ($listofpermtotest as $permtotest) {
+ if (empty($this->rights->user->self->$permtotest)) {
+ $this->rights->user->self->$permtotest = 1;
+ $this->nb_rights++;
+ }
+ }
+ // Add test on advanced permissions
+ if (!empty($conf->global->MAIN_USE_ADVANCED_PERMS)) {
+ if (empty($this->rights->user->user_advance)) {
+ $this->rights->user->user_advance = new stdClass();
+ }
+ $listofpermtotest = array('readperms', 'write');
+ foreach ($listofpermtotest as $permtotest) {
+ if (empty($this->rights->user->user_advance->$permtotest)) {
+ $this->rights->user->user_advance->$permtotest = 1;
+ $this->nb_rights++;
+ }
+ }
+ if (empty($this->rights->user->self_advance)) {
+ $this->rights->user->self_advance = new stdClass();
+ }
+ $listofpermtotest = array('readperms', 'writeperms');
+ foreach ($listofpermtotest as $permtotest) {
+ if (empty($this->rights->user->self_advance->$permtotest)) {
+ $this->rights->user->self_advance->$permtotest = 1;
+ $this->nb_rights++;
+ }
+ }
+ if (empty($this->rights->user->group_advance)) {
+ $this->rights->user->group_advance = new stdClass();
+ }
+ $listofpermtotest = array('read', 'readperms', 'write', 'delete');
+ foreach ($listofpermtotest as $permtotest) {
+ if (empty($this->rights->user) || empty($this->rights->user->group_advance->$permtotest)) {
+ $this->rights->user->group_advance->$permtotest = 1;
+ $this->nb_rights++;
+ }
+ }
+ }
+ }
+
// For backward compatibility
if (isset($this->rights->propale) && !isset($this->rights->propal)) {
$this->rights->propal = $this->rights->propale;
diff --git a/htdocs/user/group/card.php b/htdocs/user/group/card.php
index f698d1b5a07..b185ea4ce42 100644
--- a/htdocs/user/group/card.php
+++ b/htdocs/user/group/card.php
@@ -454,7 +454,7 @@ if ($action == 'create') {
print '
';
- if (is_array($permsgroupbyentity[$entity])) {
+ if (!empty($permsgroupbyentity[$entity]) && is_array($permsgroupbyentity[$entity])) {
if (in_array($obj->id, $permsgroupbyentity[$entity])) {
// Own permission by group
if ($caneditperms) {