diff --git a/doc/images/dolibarr_512x512.png b/doc/images/dolibarr_512x512.png
new file mode 100644
index 00000000000..bd8d7ac3bfd
Binary files /dev/null and b/doc/images/dolibarr_512x512.png differ
diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php
index b4f420b262c..9845502321a 100644
--- a/htdocs/accountancy/class/accountancyexport.class.php
+++ b/htdocs/accountancy/class/accountancyexport.class.php
@@ -1016,14 +1016,13 @@ class AccountancyExport
* Export format : Charlemagne
*
* @param array $objectLines data
- *
* @return void
*/
- public function exportCharlemagne($objectLines)
+ public function exportCharlemagne($objectLines)
{
global $langs;
$langs->load('compta');
-
+
$separator = "\t";
$end_line = "\n";
@@ -1045,9 +1044,9 @@ class AccountancyExport
print self::trunc($langs->transnoentitiesnoconv('Analytic') . ' 3', 15) . $separator;
print self::trunc($langs->transnoentitiesnoconv('AnalyticLabel') . ' 3', 60) . $separator;
print $end_line;
-
+
foreach($objectLines as $line) {
-
+
$date = dol_print_date($line->doc_date, '%Y%m%d');
print $date . $separator; //Date
@@ -1069,7 +1068,6 @@ class AccountancyExport
print $separator;//Analytic
print $separator;//Analytic
print $end_line;
-
}
}
diff --git a/htdocs/core/ajax/extraparams.php b/htdocs/core/ajax/extraparams.php
index 7ef25e62b8b..e039529eef7 100644
--- a/htdocs/core/ajax/extraparams.php
+++ b/htdocs/core/ajax/extraparams.php
@@ -17,7 +17,7 @@
/**
* \file /htdocs/core/ajax/extraparams.php
- * \brief File to return Ajax response on set extra parameters of elements
+ * \brief File to make Ajax action on setting extra parameters of elements
*/
if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Disables token renewal
diff --git a/htdocs/core/ajax/objectonoff.php b/htdocs/core/ajax/objectonoff.php
index 6b06cccd50c..987a59ec3fb 100644
--- a/htdocs/core/ajax/objectonoff.php
+++ b/htdocs/core/ajax/objectonoff.php
@@ -15,8 +15,9 @@
*/
/**
- * \file htdocs/core/ajax/productonoff.php
- * \brief File to set tosell and tobuy for product
+ * \file htdocs/core/ajax/objectonoff.php
+ * \brief File to set status for an object
+ * This Ajax service is called when option MAIN_DIRECT_STATUS_UPDATE is set.
*/
if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Disables token renewal
@@ -36,6 +37,13 @@ $field=GETPOST('field', 'alpha');
$element=GETPOST('element', 'alpha');
$object = new GenericObject($db);
+
+// Security check
+if (! empty($user->societe_id))
+ $socid = $user->societe_id;
+
+
+
/*
* View
*/
@@ -44,6 +52,20 @@ top_httphead();
print ''."\n";
+if ($element == 'societe' && in_array($field, array('status')))
+{
+ $result = restrictedArea($user, 'societe', $id);
+}
+elseif ($element == 'product' && in_array($field, array('tosell', 'tobuy', 'tobatch')))
+{
+ $result = restrictedArea($user, 'produit|service', $id, 'product&product', '', '', 'rowid');
+}
+else
+{
+ accessforbidden("Bad value for combination of parameters element/field.", 0, 0, 1);
+ exit;
+}
+
// Registering new values
if (($action == 'set') && ! empty($id))
$object->setValueFrom($field, $value, $element, $id);
diff --git a/htdocs/core/ajax/pingresult.php b/htdocs/core/ajax/pingresult.php
new file mode 100644
index 00000000000..9b46546f5c3
--- /dev/null
+++ b/htdocs/core/ajax/pingresult.php
@@ -0,0 +1,72 @@
+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/**
+ * \file htdocs/core/ajax/pingresult.php
+ * \brief File to save result of anonymous ping
+ * Example: captureserver/public/index.php?action=dolibarrping
+ */
+
+if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Disables token renewal
+if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1');
+if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1');
+if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1');
+if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1');
+if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1');
+
+require '../../main.inc.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
+
+$action=GETPOST('action', 'alpha');
+$hash_unique_id=GETPOST('hash_unique_id', 'alpha');
+$hash_algo=GETPOST('hash', 'alpha');
+
+
+// Security check
+if (! empty($user->societe_id))
+ $socid = $user->societe_id;
+
+$now = dol_now();
+
+
+/*
+ * View
+ */
+
+top_httphead();
+
+print ''."\n";
+
+// If ok
+if ($action == 'firstpingok')
+{
+ // Note: pings are by entities
+ dolibarr_set_const($db, 'MAIN_FIRST_PING_OK_DATE', dol_print_date($now, 'dayhourlog', 'gmt'));
+ dolibarr_set_const($db, 'MAIN_FIRST_PING_OK_ID', $hash_unique_id);
+
+ print 'First ping OK saved for entity '.$conf->entity;
+}
+// If ko
+elseif ($action == 'firstpingko')
+{
+ // Note: pings are by entities
+ dolibarr_set_const($db, 'MAIN_LAST_PING_KO_DATE', dol_print_date($now, 'dayhourlog'), 'gmt');
+ print 'First ping KO saved for entity '.$conf->entity;
+}
+else {
+ print 'Error action='.$action.' not supported';
+}
diff --git a/htdocs/core/ajax/security.php b/htdocs/core/ajax/security.php
index 9e7dea2ef95..faaddd31b23 100644
--- a/htdocs/core/ajax/security.php
+++ b/htdocs/core/ajax/security.php
@@ -17,7 +17,7 @@
/**
* \file htdocs/core/ajax/security.php
- * \brief This ajax component is used to generated has keys for security purposes
+ * \brief This ajax component is used to generated hash keys for security purposes
* like key to use into URL to protect them.
*/
diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php
index f69b4db68c1..e6d47c53d5f 100644
--- a/htdocs/core/class/commonobject.class.php
+++ b/htdocs/core/class/commonobject.class.php
@@ -2053,7 +2053,8 @@ abstract class CommonObject
return -2;
}
}
-
+
+
/**
* Change the retained warranty payments terms
*
@@ -2066,11 +2067,11 @@ abstract class CommonObject
if ($this->statut >= 0 || $this->element == 'societe')
{
$fieldname = 'retained_warranty_fk_cond_reglement';
-
+
$sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
$sql .= ' SET '.$fieldname.' = '.$id;
$sql .= ' WHERE rowid='.$this->id;
-
+
if ($this->db->query($sql))
{
$this->retained_warranty_fk_cond_reglement = $id;
@@ -5064,7 +5065,7 @@ abstract class CommonObject
//dol_syslog("attributeLabel=".$attributeLabel, LOG_DEBUG);
//dol_syslog("attributeType=".$attributeType, LOG_DEBUG);
-
+
if (!empty($attrfieldcomputed))
{
if (!empty($conf->global->MAIN_STORE_COMPUTED_EXTRAFIELDS))
@@ -6111,7 +6112,7 @@ abstract class CommonObject
{
$morecss = 'minwidth100imp';
}
- elseif ($type == 'datetime')
+ elseif ($type == 'datetime' || $type == 'timestamp')
{
$morecss = 'minwidth200imp';
}
@@ -6155,7 +6156,7 @@ abstract class CommonObject
$value='';
}
}
- elseif ($type == 'datetime')
+ elseif ($type == 'datetime' || $type == 'timestamp')
{
if(! empty($value)) {
$value=dol_print_date($value, 'dayhour');
@@ -7390,6 +7391,7 @@ abstract class CommonObject
if (!empty($id)) $sql.= ' WHERE rowid = '.$id;
elseif (!empty($ref)) $sql.= " WHERE ref = ".$this->quote($ref, $this->fields['ref']);
else $sql.=' WHERE 1 = 1'; // usage with empty id and empty ref is very rare
+ if (empty($id) && isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql.=' AND entity IN ('.getEntity($this->table_element).')';
if ($morewhere) $sql.= $morewhere;
$sql.=' LIMIT 1'; // This is a fetch, to be sure to get only one record
diff --git a/htdocs/core/class/fileupload.class.php b/htdocs/core/class/fileupload.class.php
index ee090fed65d..2f0ae34b529 100644
--- a/htdocs/core/class/fileupload.class.php
+++ b/htdocs/core/class/fileupload.class.php
@@ -17,7 +17,7 @@
*/
/**
- * \file htdocs/core/ajax/fileupload.php
+ * \file htdocs/core/ajax/fileupload.class.php
* \brief File to return Ajax response on file upload
*/
diff --git a/htdocs/core/lib/ajax.lib.php b/htdocs/core/lib/ajax.lib.php
index a96e63a4f43..43f4723d695 100644
--- a/htdocs/core/lib/ajax.lib.php
+++ b/htdocs/core/lib/ajax.lib.php
@@ -538,11 +538,12 @@ function ajax_constantonoff($code, $input = array(), $entity = null, $revertonof
}
/**
- * On/off button for object
+ * On/off button to change status of an object
+ * This is called when MAIN_DIRECT_STATUS_UPDATE is set and it use tha ajax service objectonoff.php
*
* @param Object $object Object to set
* @param string $code Name of constant : status or status_buy for product by example
- * @param string $field Name of database field : tosell or tobuy for product by example
+ * @param string $field Name of database field : 'tosell' or 'tobuy' for product by example
* @param string $text_on Text if on
* @param string $text_off Text if off
* @param array $input Array of type->list of CSS element to switch. Example: array('disabled'=>array(0=>'cssid'))
diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php
index 051f3a5392a..2ee5a45c010 100644
--- a/htdocs/core/lib/security.lib.php
+++ b/htdocs/core/lib/security.lib.php
@@ -279,7 +279,7 @@ function restrictedArea($user, $features, $objectid = 0, $tableandshare = '', $f
// Check write permission from module (we need to know write permission to create but also to delete drafts record)
$createok=1; $nbko=0;
- if (GETPOST('action', 'aZ09') == 'create' || ((GETPOST("action", "aZ09") == 'confirm_delete' && GETPOST("confirm", "aZ09") == 'yes') || GETPOST("action", "aZ09") == 'delete'))
+ if (GETPOST('action', 'aZ09') == 'create' || GETPOST('action', 'aZ09') == 'update' || ((GETPOST("action", "aZ09") == 'confirm_delete' && GETPOST("confirm", "aZ09") == 'yes') || GETPOST("action", "aZ09") == 'delete'))
{
foreach ($featuresarray as $feature)
{
@@ -329,7 +329,7 @@ function restrictedArea($user, $features, $objectid = 0, $tableandshare = '', $f
// If a or and at least one ok
if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) $createok=1;
- if (GETPOST('action', 'aZ09') == 'create' && ! $createok) accessforbidden();
+ if ((GETPOST('action', 'aZ09') == 'create' || GETPOST('action', 'aZ09') == 'update') && ! $createok) accessforbidden();
//print "Write access is ok";
}
diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php
index a764e2df47c..c7cb9776aeb 100644
--- a/htdocs/expensereport/card.php
+++ b/htdocs/expensereport/card.php
@@ -996,6 +996,34 @@ if (empty($reshook))
}
}
+ if ($action == 'set_unpaid' && $id > 0 && $user->rights->expensereport->to_paid)
+ {
+ $object = new ExpenseReport($db);
+ $object->fetch($id);
+
+ $result = $object->set_unpaid($user);
+
+ if ($result > 0)
+ {
+ // Define output language
+ if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
+ {
+ $outputlangs = $langs;
+ $newlang = '';
+ if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09');
+ if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang;
+ if (! empty($newlang)) {
+ $outputlangs = new Translate("", $conf);
+ $outputlangs->setDefaultLang($newlang);
+ }
+ $model=$object->modelpdf;
+ $ret = $object->fetch($id); // Reload to get new records
+
+ $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
+ }
+ }
+ }
+
if ($action == 'set_paid' && $id > 0 && $user->rights->expensereport->to_paid)
{
$object = new ExpenseReport($db);
@@ -1679,7 +1707,7 @@ else
if ($action == 'cancel')
{
- $array_input = array('text'=>$langs->trans("ConfirmCancelTrip"), array('type'=>"text",'label'=>''.$langs->trans("Comment").'','name'=>"detail_cancel",'size'=>"50",'value'=>""));
+ $array_input = array('text'=>$langs->trans("ConfirmCancelTrip"), array('type'=>"text",'label'=>''.$langs->trans("Comment").'','name'=>"detail_cancel",'value'=>""));
$formconfirm=$form->formconfirm($_SEVER["PHP_SELF"]."?id=".$id, $langs->trans("Cancel"), "", "confirm_cancel", $array_input, "", 1);
}
@@ -1690,7 +1718,7 @@ else
if ($action == 'refuse') // Deny
{
- $array_input = array('text'=>$langs->trans("ConfirmRefuseTrip"), array('type'=>"text",'label'=>$langs->trans("Comment"),'name'=>"detail_refuse",'size'=>"50",'value'=>""));
+ $array_input = array('text'=>$langs->trans("ConfirmRefuseTrip"), array('type'=>"text",'label'=>$langs->trans("Comment"),'name'=>"detail_refuse",'value'=>""));
$formconfirm=$form->formconfirm($_SERVER["PHP_SELF"]."?id=".$id, $langs->trans("Deny"), '', "confirm_refuse", $array_input, "yes", 1);
}
@@ -2662,8 +2690,8 @@ if ($action != 'create' && $action != 'edit')
}
- // If status is Appoved
- // --------------------
+ // If status is Approved
+ // ---------------------
if ($user->rights->expensereport->approve && $object->fk_statut == ExpenseReport::STATUS_APPROVED)
{
@@ -2707,9 +2735,15 @@ if ($action != 'create' && $action != 'edit')
print '
';
}
+ if ($user->rights->expensereport->to_paid && $object->paid && $object->fk_statut == ExpenseReport::STATUS_CLOSED)
+ {
+ // Set unpaid
+ print '';
+ }
+
// Clone
if ($user->rights->expensereport->creer) {
- print '';
+ print '';
}
/* If draft, validated, cancel, and user can create, he can always delete its card before it is approved */
diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php
index 272125530e3..9b1a62ed402 100644
--- a/htdocs/expensereport/class/expensereport.class.php
+++ b/htdocs/expensereport/class/expensereport.class.php
@@ -1397,12 +1397,12 @@ class ExpenseReport extends CommonObject
// phpcs:enable
$error = 0;
- if ($this->fk_c_deplacement_statuts != 5)
+ if ($this->paid)
{
$this->db->begin();
$sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
- $sql.= " SET fk_statut = 5";
+ $sql.= " SET paid = 0";
$sql.= ' WHERE rowid = '.$this->id;
dol_syslog(get_class($this)."::set_unpaid sql=".$sql, LOG_DEBUG);
diff --git a/htdocs/expensereport/payment/card.php b/htdocs/expensereport/payment/card.php
index 73da11f4619..890884b2e37 100644
--- a/htdocs/expensereport/payment/card.php
+++ b/htdocs/expensereport/payment/card.php
@@ -286,7 +286,6 @@ else
dol_print_error($db);
}
-print '';
/*
diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang
index 5f4a9ff0bba..53535e58b46 100644
--- a/htdocs/langs/en_US/bills.lang
+++ b/htdocs/langs/en_US/bills.lang
@@ -95,6 +95,7 @@ PaymentHigherThanReminderToPay=Payment higher than reminder to pay
HelpPaymentHigherThanReminderToPay=Attention, the payment amount of one or more bills is higher than the outstanding amount to pay.
Edit your entry, otherwise confirm and consider creating a credit note for the excess received for each overpaid invoice.
HelpPaymentHigherThanReminderToPaySupplier=Attention, the payment amount of one or more bills is higher than the outstanding amount to pay.
Edit your entry, otherwise confirm and consider creating a credit note for the excess paid for each overpaid invoice.
ClassifyPaid=Classify 'Paid'
+ClassifyUnPaid=Classify 'Unpaid'
ClassifyPaidPartially=Classify 'Paid partially'
ClassifyCanceled=Classify 'Abandoned'
ClassifyClosed=Classify 'Closed'
diff --git a/htdocs/langs/fr_FR/bills.lang b/htdocs/langs/fr_FR/bills.lang
index 41f5aca717c..ca251ed0d93 100644
--- a/htdocs/langs/fr_FR/bills.lang
+++ b/htdocs/langs/fr_FR/bills.lang
@@ -96,6 +96,7 @@ HelpPaymentHigherThanReminderToPay=Attention, le montant de paiement pour une ou
HelpPaymentHigherThanReminderToPaySupplier=Attention, le montant de paiement pour une ou plusieurs factures est supérieur au reste à payer.
Corrigez votre saisie, sinon, confirmez et pensez à créer un avoir pour l'excédent pour chaque facture surpayée.
ClassifyPaid=Classer 'Payée'
ClassifyPaidPartially=Classer 'Payée partiellement'
+ClassifyUnPaid=Classer 'Non payée'
ClassifyCanceled=Classer 'Abandonnée'
ClassifyClosed=Classer 'Fermée'
ClassifyUnBilled=Classer 'Non facturée'
diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php
index bf4c40a4176..7b983ca05eb 100644
--- a/htdocs/main.inc.php
+++ b/htdocs/main.inc.php
@@ -1124,6 +1124,7 @@ function top_httphead($contenttype = 'text/html', $forcenocache = 0)
if ($contenttype == 'text/html' ) header("Content-Type: text/html; charset=".$conf->file->character_set_client);
else header("Content-Type: ".$contenttype);
+
// Security options
header("X-Content-Type-Options: nosniff"); // With the nosniff option, if the server says the content is text/html, the browser will render it as text/html (note that most browsers now force this option to on)
if (! defined('XFRAMEOPTIONS_ALLOWALL')) header("X-Frame-Options: SAMEORIGIN"); // Frames allowed only if on same domain (stop some XSS attacks)
@@ -2319,6 +2320,51 @@ if (! function_exists("llxFooter"))
print "\n\n";
print ''."\n";
+ // Add code for the asynchronous anonymous first ping (for telemetry)
+ if (($_SERVER["PHP_SELF"] == DOL_URL_ROOT.'/index.php') || GETPOST('forceping', 'alpha'))
+ {
+ if (empty($conf->global->MAIN_FIRST_PING_OK_DATE)
+ || (! empty($conf->file->instance_unique_id) && (md5($conf->file->instance_unique_id) != $conf->global->MAIN_FIRST_PING_OK_ID))
+ || GETPOST('forceping', 'alpha'))
+ {
+ print "\n".''."\n";
+ print "\n\n";
+ ?>
+
+ \n";
print "