';
if (empty($conf->global->SOCIETE_DISABLE_CONTACTS)) {
$objsoc = new Societe($db);
$objsoc->fetch($object->socid);
diff --git a/htdocs/contact/project.php b/htdocs/contact/project.php
new file mode 100644
index 00000000000..b05709f019a
--- /dev/null
+++ b/htdocs/contact/project.php
@@ -0,0 +1,117 @@
+
+ *
+ * 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/contact/project.php
+ * \ingroup contact
+ * \brief Page of third party projects
+ */
+
+require '../main.inc.php';
+require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
+
+$langs->loadLangs(array("contacts", "companies", "projects"));
+
+// Security check
+$id = GETPOST('id', 'int');
+$result = restrictedArea($user, 'contact', $id, 'socpeople&societe');
+
+// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
+$hookmanager->initHooks(array('projectcontact'));
+
+/*
+ * Actions
+ */
+
+$parameters = array('id' => $id);
+$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
+if ($reshook < 0) {
+ setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
+}
+
+/*
+ * View
+ */
+
+$form = new Form($db);
+
+if ($id) {
+ require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
+ require_once DOL_DOCUMENT_ROOT.'/core/lib/contact.lib.php';
+
+ $object = new Contact($db);
+
+ $result = $object->fetch($id);
+ if (empty($object->thirdparty)) {
+ $object->fetch_thirdparty();
+ }
+ $socid = $object->thirdparty->id;
+ $title = $langs->trans("Projects");
+ if (! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/thirdpartynameonly/', $conf->global->MAIN_HTML_TITLE) && $object->name) {
+ $title = $object->name." - ".$title;
+ }
+ llxHeader('', $title);
+
+ if (! empty($conf->notification->enabled)) {
+ $langs->load("mails");
+ }
+ $head = contact_prepare_head($object);
+
+ print dol_get_fiche_head($head, 'project', $langs->trans("Contact"), -1, 'contact');
+
+ $linkback = '
'.$langs->trans("BackToList").'';
+
+ $morehtmlref = '
';
+ if (empty($conf->global->SOCIETE_DISABLE_CONTACTS) && !empty($socid)) {
+ $object->thirdparty->fetch($socid);
+ // Thirdparty
+ $morehtmlref .= $langs->trans('ThirdParty').' : ';
+ if ($object->thirdparty->id > 0) {
+ $morehtmlref .= $object->thirdparty->getNomUrl(1, 'contact');
+ } else {
+ $morehtmlref .= $langs->trans("ContactNotLinkedToCompany");
+ }
+ }
+ $morehtmlref .= '
';
+
+ dol_banner_tab($object, 'id', $linkback, ($user->socid ? 0 : 1), 'rowid', 'nom', $morehtmlref);
+
+ print '
';
+
+ print '
';
+ print '
';
+
+ // Civility
+ print '| '.$langs->trans("UserTitle").' | ';
+ print $object->getCivilityLabel();
+ print ' |
';
+
+ print '
';
+
+ print '
';
+
+ print dol_get_fiche_end();
+ print '
';
+
+ // Projects list
+ $result = show_contacts_projects($conf, $langs, $db, $object, $_SERVER["PHP_SELF"].'?id='.$object->id, 1);
+}
+
+// End of page
+llxFooter();
+$db->close();
diff --git a/htdocs/contrat/agenda.php b/htdocs/contrat/agenda.php
index eeeccddd671..d654ac38d9f 100644
--- a/htdocs/contrat/agenda.php
+++ b/htdocs/contrat/agenda.php
@@ -57,8 +57,8 @@ if ($user->socid) {
$result = restrictedArea($user, 'contrat', $id, '');
$limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
-$sortfield = GETPOST("sortfield", 'alpha');
-$sortorder = GETPOST("sortorder", 'alpha');
+$sortfield = GETPOST('sortfield', 'aZ09comma');
+$sortorder = GETPOST('sortorder', 'aZ09comma');
$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
if (empty($page) || $page == -1) {
$page = 0;
@@ -245,6 +245,8 @@ if ($id > 0) {
$newcardbutton = '';
if (!empty($conf->agenda->enabled)) {
if (!empty($user->rights->agenda->myactions->create) || !empty($user->rights->agenda->allactions->create)) {
+ $backtopage = $_SERVER['PHP_SELF'].'?id='.$object->id;
+ $out = '&origin='.$object->element.'&originid='.$object->id.'&backtopage='.urlencode($backtopage);
$newcardbutton .= dolGetButtonTitle($langs->trans('AddAction'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/comm/action/card.php?action=create'.$out);
}
}
diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php
index c52b57e305f..3febcc868a0 100644
--- a/htdocs/contrat/card.php
+++ b/htdocs/contrat/card.php
@@ -40,6 +40,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/modules/contract/modules_contract.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
+require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
if (!empty($conf->propal->enabled)) {
require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
}
@@ -248,6 +249,10 @@ if (empty($reshook)) {
if ($element == 'propal') {
$element = 'comm/propal'; $subelement = 'propal';
}
+ if ($element == 'invoice' || $element == 'facture') {
+ $element = 'compta/facture';
+ $subelement = 'facture';
+ }
$object->origin = $origin;
$object->origin_id = $originid;
@@ -1040,6 +1045,10 @@ if ($action == 'create') {
if ($element == 'propal') {
$element = 'comm/propal'; $subelement = 'propal';
}
+ if ($element == 'invoice' || $element == 'facture') {
+ $element = 'compta/facture';
+ $subelement = 'facture';
+ }
dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
@@ -1537,11 +1546,11 @@ if ($action == 'create') {
// Margin
if (!empty($conf->margin->enabled) && !empty($conf->global->MARGIN_SHOW_ON_CONTRACT)) {
- print '
'.price($objp->pa_ht).' | ';
+ print '
'.price($objp->pa_ht).' | ';
}
// Icon move, update et delete (statut contrat 0=brouillon,1=valide,2=ferme)
- print '
';
+ print ' | ';
if ($user->rights->contrat->creer && count($arrayothercontracts) && ($object->statut >= 0)) {
print '';
print '';
diff --git a/htdocs/contrat/document.php b/htdocs/contrat/document.php
index b4cf2fc1fbf..953fd0002d2 100644
--- a/htdocs/contrat/document.php
+++ b/htdocs/contrat/document.php
@@ -55,8 +55,8 @@ $result = restrictedArea($user, 'contrat', $id);
// Get parameters
$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit;
-$sortfield = GETPOST("sortfield", 'alpha');
-$sortorder = GETPOST("sortorder", 'alpha');
+$sortfield = GETPOST('sortfield', 'aZ09comma');
+$sortorder = GETPOST('sortorder', 'aZ09comma');
$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
if (empty($page) || $page == -1) {
$page = 0;
diff --git a/htdocs/contrat/list.php b/htdocs/contrat/list.php
index ed980f9e86e..e6446e3585b 100644
--- a/htdocs/contrat/list.php
+++ b/htdocs/contrat/list.php
@@ -79,8 +79,8 @@ $search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_en
$optioncss = GETPOST('optioncss', 'alpha');
$limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
-$sortfield = GETPOST("sortfield", 'alpha');
-$sortorder = GETPOST("sortorder", 'alpha');
+$sortfield = GETPOST('sortfield', 'aZ09comma');
+$sortorder = GETPOST('sortorder', 'aZ09comma');
$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
if (empty($page) || $page == -1) {
$page = 0;
diff --git a/htdocs/contrat/services_list.php b/htdocs/contrat/services_list.php
index 31621ba420a..39dfe336a31 100644
--- a/htdocs/contrat/services_list.php
+++ b/htdocs/contrat/services_list.php
@@ -39,8 +39,8 @@ $optioncss = GETPOST('optioncss', 'aZ09');
$massaction = GETPOST('massaction', 'alpha');
$limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
-$sortfield = GETPOST("sortfield", 'alpha');
-$sortorder = GETPOST("sortorder", 'alpha');
+$sortfield = GETPOST('sortfield', 'aZ09comma');
+$sortorder = GETPOST('sortorder', 'aZ09comma');
$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
if (empty($page) || $page == -1) {
$page = 0;
diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php
index 913c0cb768e..602897d34f9 100644
--- a/htdocs/core/actions_massactions.inc.php
+++ b/htdocs/core/actions_massactions.inc.php
@@ -81,7 +81,7 @@ if (!$error && $massaction == 'confirm_presend') {
$listofobjectref = array();
$contactidtosend = array();
$attachedfilesThirdpartyObj = array();
- $oneemailperrecipient = (GETPOST('oneemailperrecipient') == 'on' ? 1 : 0);
+ $oneemailperrecipient = (GETPOST('oneemailperrecipient', 'int') ? 1 : 0);
if (!$error) {
$thirdparty = new Societe($db);
@@ -657,8 +657,8 @@ if ($massaction == 'confirm_createbills') { // Create bills from orders.
// If we want one invoice per order or if there is no first invoice yet for this thirdparty.
$objecttmp->socid = $cmd->socid;
$objecttmp->type = $objecttmp::TYPE_STANDARD;
- $objecttmp->cond_reglement_id = ($cmd->cond_reglement_id || $cmd->thirdparty->cond_reglement_id);
- $objecttmp->mode_reglement_id = ($cmd->mode_reglement_id || $cmd->thirdparty->mode_reglement_id);
+ $objecttmp->cond_reglement_id = !empty($cmd->cond_reglement_id) ? $cmd->cond_reglement_id : $cmd->thirdparty->cond_reglement_id;
+ $objecttmp->mode_reglement_id = !empty($cmd->mode_reglement_id) ? $cmd->mode_reglement_id : $cmd->thirdparty->mode_reglement_id;
$objecttmp->fk_project = $cmd->fk_project;
$objecttmp->multicurrency_code = $cmd->multicurrency_code;
diff --git a/htdocs/core/actions_setmoduleoptions.inc.php b/htdocs/core/actions_setmoduleoptions.inc.php
index 43ddd23f13d..fbf526fd58e 100644
--- a/htdocs/core/actions_setmoduleoptions.inc.php
+++ b/htdocs/core/actions_setmoduleoptions.inc.php
@@ -29,13 +29,13 @@
// $formSetup may be defined
-if ($action == 'update' && !empty($formSetup) && is_object($formSetup)) {
+if ($action == 'update' && !empty($formSetup) && is_object($formSetup) && !empty($user->admin)) {
$formSetup->saveConfFromPost();
return;
}
-if ($action == 'update' && is_array($arrayofparameters)) {
+if ($action == 'update' && is_array($arrayofparameters) && !empty($user->admin)) {
$db->begin();
foreach ($arrayofparameters as $key => $val) {
@@ -72,8 +72,37 @@ if ($action == 'update' && is_array($arrayofparameters)) {
}
}
+if ($action == 'deletefile' && $modulepart == 'doctemplates' && !empty($user->admin)) {
+ include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
+ $keyforuploaddir = GETPOST('keyforuploaddir', 'aZ09');
+
+ $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim(getDolGlobalString($keyforuploaddir))));
+ foreach ($listofdir as $key => $tmpdir) {
+ $tmpdir = preg_replace('/DOL_DATA_ROOT\/*/', '', $tmpdir); // Clean string if we found a hardcoded DOL_DATA_ROOT
+ if (!$tmpdir) {
+ unset($listofdir[$key]);
+ continue;
+ }
+ $tmpdir = DOL_DATA_ROOT.'/'.$tmpdir; // Complete with DOL_DATA_ROOT. Only files into DOL_DATA_ROOT can be reach/set
+ if (!is_dir($tmpdir)) {
+ if (empty($nomessageinsetmoduleoptions)) {
+ setEventMessages($langs->trans("ErrorDirNotFound", $tmpdir), null, 'warnings');
+ }
+ } else {
+ $upload_dir = $tmpdir;
+ break; // So we take the first directory found into setup $conf->global->$keyforuploaddir
+ }
+ }
+
+ $filetodelete = $tmpdir.'/'.GETPOST('file');
+ $result = dol_delete_file($filetodelete);
+ if ($result > 0) {
+ setEventMessages($langs->trans("FileWasRemoved", GETPOST('file')), null, 'mesgs');
+ }
+}
+
// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...)
-if ($action == 'setModuleOptions') {
+if ($action == 'setModuleOptions' && !empty($user->admin)) {
$db->begin();
// Process common param fields
@@ -97,20 +126,22 @@ if ($action == 'setModuleOptions') {
if (GETPOST('upload', 'alpha') && GETPOST('keyforuploaddir', 'aZ09')) {
include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
$keyforuploaddir = GETPOST('keyforuploaddir', 'aZ09');
- $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim($conf->global->$keyforuploaddir)));
+ $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim(getDolGlobalString($keyforuploaddir))));
foreach ($listofdir as $key => $tmpdir) {
$tmpdir = trim($tmpdir);
- $tmpdir = preg_replace('/DOL_DATA_ROOT/', DOL_DATA_ROOT, $tmpdir);
+ $tmpdir = preg_replace('/DOL_DATA_ROOT\/*/', '', $tmpdir); // Clean string if we found a hardcoded DOL_DATA_ROOT
if (!$tmpdir) {
unset($listofdir[$key]);
continue;
}
+ $tmpdir = DOL_DATA_ROOT.'/'.$tmpdir; // Complete with DOL_DATA_ROOT. Only files into DOL_DATA_ROOT can be reach/set
if (!is_dir($tmpdir)) {
if (empty($nomessageinsetmoduleoptions)) {
setEventMessages($langs->trans("ErrorDirNotFound", $tmpdir), null, 'warnings');
}
} else {
$upload_dir = $tmpdir;
+ break; // So we take the first directory found into setup $conf->global->$keyforuploaddir
}
}
if ($upload_dir) {
diff --git a/htdocs/core/ajax/check_notifications.php b/htdocs/core/ajax/check_notifications.php
index bbbc95a19c5..a5efb52e787 100644
--- a/htdocs/core/ajax/check_notifications.php
+++ b/htdocs/core/ajax/check_notifications.php
@@ -170,8 +170,10 @@ if (empty($_SESSION['auto_check_events_not_before']) || $time >= $_SESSION['auto
$event['code'] = $obj->code;
$event['label'] = $obj->label;
$event['location'] = $obj->location;
- $event['reminder_date_formated'] = dol_print_date($db->jdate($obj->dateremind), 'standard');
- $event['event_date_start_formated'] = dol_print_date($db->jdate($obj->datep), 'standard');
+ $event['reminder_date_formated_tzserver'] = dol_print_date($db->jdate($obj->dateremind), 'standard', 'tzserver');
+ $event['event_date_start_formated_tzserver'] = dol_print_date($db->jdate($obj->datep), 'standard', 'tzserver');
+ $event['reminder_date_formated'] = dol_print_date($db->jdate($obj->dateremind), 'standard', 'tzuser');
+ $event['event_date_start_formated'] = dol_print_date($db->jdate($obj->datep), 'standard', 'tzuser');
$eventfound[$obj->id_agenda] = $event;
}
diff --git a/htdocs/core/ajax/onlineSign.php b/htdocs/core/ajax/onlineSign.php
index bf484dc1c45..5110918541f 100644
--- a/htdocs/core/ajax/onlineSign.php
+++ b/htdocs/core/ajax/onlineSign.php
@@ -60,12 +60,15 @@ $SECUREKEY = GETPOST("securekey"); // Secure key
$error = 0;
$response = "";
-// Check securitykey
-$securekeyseed = $conf->global->PROPOSAL_ONLINE_SIGNATURE_SECURITY_TOKEN;
$type = $mode;
-$calculatedsecuritykey = dol_hash($securekeyseed.$type.$ref, '0');
-if ($calculatedsecuritykey != $SECUREKEY) {
+// Check securitykey
+$securekeyseed = '';
+if ($type == 'proposal') {
+ $securekeyseed = $conf->global->PROPOSAL_ONLINE_SIGNATURE_SECURITY_TOKEN;
+}
+
+if (!dol_verifyHash($securekeyseed.$type.$ref, $SECUREKEY, '0')) {
http_response_code(403);
print 'Bad value for securitykey. Value provided '.dol_escape_htmltag($SECUREKEY).' does not match expected value for ref='.dol_escape_htmltag($ref);
exit(-1);
@@ -110,24 +113,39 @@ if ($action == "importSignature") {
$return = file_put_contents($upload_dir.$filename, $data);
if ($return == false) {
$error++;
- $response = 'error file_put_content';
+ $response = 'Error file_put_content: failed to create signature file.';
}
}
if (!$error) {
+ $newpdffilename = $upload_dir.$ref."_signed-".$date.".pdf";
+
$pdf = pdf_getInstance();
$pdf->Open();
$pdf->AddPage();
- $pagecount = $pdf->setSourceFile($upload_dir.$ref.".pdf");
+ $pagecount = $pdf->setSourceFile($upload_dir.$ref.".pdf"); // original PDF
$tppl = $pdf->importPage(1);
$pdf->useTemplate($tppl);
- $pdf->Image($upload_dir.$filename, 129, 239.6, 60, 15);
+ $pdf->Image($upload_dir.$filename, 129, 239.6, 60, 15); // FIXME Position will be wrong with non A4 format. Use a value from width and height of page minus relative offset.
$pdf->Close();
- $pdf->Output($upload_dir.$ref."_signed-".$date.".pdf", "F");
+ $pdf->Output($newpdffilename, "F");
+
+ $db->begin();
+
+ // Index the new file and update the last_main_doc property of object.
+ $object->indexFile($newpdffilename, 1);
+
+ $online_sign_ip = getUserRemoteIP();
+ $online_sign_name = ''; // TODO Ask name on form to sign
$sql = "UPDATE ".MAIN_DB_PREFIX."propal";
- $sql .= " SET fk_statut = ".((int) $object::STATUS_SIGNED).", note_private = '".$object->note_private."', date_signature='".$db->idate(dol_now())."'";
+ $sql .= " SET fk_statut = ".((int) $object::STATUS_SIGNED).", note_private = '".$db->escape($object->note_private)."',";
+ $sql .= " date_signature = '".$db->idate(dol_now())."',";
+ $sql .= " online_sign_ip = '".$db->escape($online_sign_ip)."'";
+ if ($online_sign_name) {
+ $sql .= ", online_sign_name = '".$db->escape($online_sign_name)."'";
+ }
$sql .= " WHERE rowid = ".((int) $object->id);
dol_syslog(__METHOD__, LOG_DEBUG);
diff --git a/htdocs/core/boxes/box_accountancy_last_manual_entries.php b/htdocs/core/boxes/box_accountancy_last_manual_entries.php
index b1e4a637046..96abd8699f3 100644
--- a/htdocs/core/boxes/box_accountancy_last_manual_entries.php
+++ b/htdocs/core/boxes/box_accountancy_last_manual_entries.php
@@ -134,7 +134,7 @@ class box_accountancy_last_manual_entries extends ModeleBoxes
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="nowraponall right"',
+ 'td' => 'class="nowraponall right amount"',
'text' => price($amount, 0, $langs, 0, -1, -1, $conf->currency),
);
diff --git a/htdocs/core/boxes/box_activity.php b/htdocs/core/boxes/box_activity.php
index 487c2170a4a..371a7a0dbed 100644
--- a/htdocs/core/boxes/box_activity.php
+++ b/htdocs/core/boxes/box_activity.php
@@ -174,7 +174,7 @@ class box_activity extends ModeleBoxes
$totalnb += $data[$j]->nb;
$this->info_box_contents[$line][3] = array(
- 'td' => 'class="nowraponall right"',
+ 'td' => 'class="nowraponall right amount"',
'text' => price($data[$j]->Mnttot, 1, $langs, 0, 0, -1, $conf->currency),
);
$this->info_box_contents[$line][4] = array(
@@ -262,7 +262,7 @@ class box_activity extends ModeleBoxes
$totalnb += $data[$j]->nb;
$this->info_box_contents[$line][3] = array(
- 'td' => 'class="nowraponall right"',
+ 'td' => 'class="nowraponall right amount"',
'text' => price($data[$j]->Mnttot, 1, $langs, 0, 0, -1, $conf->currency),
);
$this->info_box_contents[$line][4] = array(
@@ -350,7 +350,7 @@ class box_activity extends ModeleBoxes
);
$this->info_box_contents[$line][3] = array(
- 'td' => 'class="nowraponall right"',
+ 'td' => 'class="nowraponall right amount"',
'text' => price($data[$j]->Mnttot, 1, $langs, 0, 0, -1, $conf->currency)
);
@@ -433,7 +433,7 @@ class box_activity extends ModeleBoxes
);
$totalnb += $data[$j]->nb;
$this->info_box_contents[$line][3] = array(
- 'td' => 'class="nowraponall right"',
+ 'td' => 'class="nowraponall right amount"',
'text' => price($data[$j]->Mnttot, 1, $langs, 0, 0, -1, $conf->currency),
);
$this->info_box_contents[$line][4] = array(
diff --git a/htdocs/core/boxes/box_commandes.php b/htdocs/core/boxes/box_commandes.php
index abf9baf06f3..ae939afe25c 100644
--- a/htdocs/core/boxes/box_commandes.php
+++ b/htdocs/core/boxes/box_commandes.php
@@ -163,7 +163,7 @@ class box_commandes extends ModeleBoxes
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="nowraponall right"',
+ 'td' => 'class="nowraponall right amount"',
'text' => price($objp->total_ht, 0, $langs, 0, -1, -1, $conf->currency),
);
diff --git a/htdocs/core/boxes/box_comptes.php b/htdocs/core/boxes/box_comptes.php
index f42b7a2ef7c..5570051a065 100644
--- a/htdocs/core/boxes/box_comptes.php
+++ b/htdocs/core/boxes/box_comptes.php
@@ -141,8 +141,11 @@ class box_comptes extends ModeleBoxes
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="right nowraponall"',
- 'text' => price($solde, 0, $langs, 1, -1, -1, $objp->currency_code)
+ 'td' => 'class="nowraponall right amount"',
+ 'text' => ''
+ .price($solde, 0, $langs, 1, -1, -1, $objp->currency_code)
+ .'',
+ 'asis' => 1,
);
$line++;
@@ -161,7 +164,7 @@ class box_comptes extends ModeleBoxes
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="liste_total right nowraponall"',
+ 'td' => 'class="liste_total nowraponall right amount"',
'text' => price($solde, 0, $langs, 0, -1, -1, $key)
);
$line++;
diff --git a/htdocs/core/boxes/box_dolibarr_state_board.php b/htdocs/core/boxes/box_dolibarr_state_board.php
index 21bf58b859f..0381b493448 100644
--- a/htdocs/core/boxes/box_dolibarr_state_board.php
+++ b/htdocs/core/boxes/box_dolibarr_state_board.php
@@ -105,7 +105,8 @@ class box_dolibarr_state_board extends ModeleBoxes
'supplier_invoices',
'contracts',
'interventions',
- 'ticket'
+ 'ticket',
+ 'dolresource'
);
$conditions = array(
'users' => $user->rights->user->user->lire,
@@ -132,7 +133,8 @@ class box_dolibarr_state_board extends ModeleBoxes
'projects' => !empty($conf->projet->enabled) && $user->rights->projet->lire,
'expensereports' => !empty($conf->expensereport->enabled) && $user->rights->expensereport->lire,
'holidays' => !empty($conf->holiday->enabled) && $user->rights->holiday->read,
- 'ticket' => !empty($conf->ticket->enabled) && $user->rights->ticket->read
+ 'ticket' => !empty($conf->ticket->enabled) && $user->rights->ticket->read,
+ 'dolresource' => !empty($conf->resource->enabled) && $user->rights->resource->read
);
$classes = array(
'users' => 'User',
@@ -156,6 +158,7 @@ class box_dolibarr_state_board extends ModeleBoxes
'expensereports' => 'ExpenseReport',
'holidays' => 'Holiday',
'ticket' => 'Ticket',
+ 'dolresource' => 'Dolresource'
);
$includes = array(
'users' => DOL_DOCUMENT_ROOT . "/user/class/user.class.php",
@@ -178,7 +181,8 @@ class box_dolibarr_state_board extends ModeleBoxes
'projects' => DOL_DOCUMENT_ROOT . "/projet/class/project.class.php",
'expensereports' => DOL_DOCUMENT_ROOT . "/expensereport/class/expensereport.class.php",
'holidays' => DOL_DOCUMENT_ROOT . "/holiday/class/holiday.class.php",
- 'ticket' => DOL_DOCUMENT_ROOT . "/ticket/class/ticket.class.php"
+ 'ticket' => DOL_DOCUMENT_ROOT . "/ticket/class/ticket.class.php",
+ 'dolresource' => DOL_DOCUMENT_ROOT . "/resource/class/dolresource.class.php"
);
$links = array(
'users' => DOL_URL_ROOT . '/user/list.php',
@@ -201,7 +205,8 @@ class box_dolibarr_state_board extends ModeleBoxes
'projects' => DOL_URL_ROOT . '/projet/list.php?mainmenu=project',
'expensereports' => DOL_URL_ROOT . '/expensereport/list.php?mainmenu=hrm&leftmenu=expensereport',
'holidays' => DOL_URL_ROOT . '/holiday/list.php?mainmenu=hrm&leftmenu=holiday',
- 'ticket' => DOL_URL_ROOT . '/ticket/list.php?leftmenu=ticket'
+ 'ticket' => DOL_URL_ROOT . '/ticket/list.php?leftmenu=ticket',
+ 'dolresource' => DOL_URL_ROOT . '/resource/list.php?mainmenu=tools',
);
$titres = array(
'users' => "Users",
@@ -225,6 +230,7 @@ class box_dolibarr_state_board extends ModeleBoxes
'expensereports' => "ExpenseReports",
'holidays' => "Holidays",
'ticket' => "Ticket",
+ 'dolresource' => "Resources",
);
$langfile = array(
'customers' => "companies",
diff --git a/htdocs/core/boxes/box_factures_fourn.php b/htdocs/core/boxes/box_factures_fourn.php
index ae905d5d468..42a945b9289 100644
--- a/htdocs/core/boxes/box_factures_fourn.php
+++ b/htdocs/core/boxes/box_factures_fourn.php
@@ -183,7 +183,7 @@ class box_factures_fourn extends ModeleBoxes
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="right nowraponall"',
+ 'td' => 'class="nowraponall right amount"',
'text' => price($objp->total_ht, 0, $langs, 0, -1, -1, $conf->currency),
);
diff --git a/htdocs/core/boxes/box_factures_fourn_imp.php b/htdocs/core/boxes/box_factures_fourn_imp.php
index cfef8801414..a421706e855 100644
--- a/htdocs/core/boxes/box_factures_fourn_imp.php
+++ b/htdocs/core/boxes/box_factures_fourn_imp.php
@@ -170,7 +170,7 @@ class box_factures_fourn_imp extends ModeleBoxes
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="nowraponall right"',
+ 'td' => 'class="nowraponall right amount"',
'text' => price($objp->total_ht, 0, $langs, 0, -1, -1, $conf->currency),
);
diff --git a/htdocs/core/boxes/box_funnel_of_prospection.php b/htdocs/core/boxes/box_funnel_of_prospection.php
index 89ed2215732..cdaa9298f63 100644
--- a/htdocs/core/boxes/box_funnel_of_prospection.php
+++ b/htdocs/core/boxes/box_funnel_of_prospection.php
@@ -219,7 +219,7 @@ class box_funnel_of_prospection extends ModeleBoxes
if (!$conf->use_javascript_ajax) {
$stringtoprint .= ' | ';
$stringtoprint .= '| '.$labelStatus.' | ';
- $stringtoprint .= ''.price((isset($valsamount[$status]) ? (float) $valsamount[$status] : 0), 0, '', 1, -1, -1, $conf->currency).' | ';
+ $stringtoprint .= ''.price((isset($valsamount[$status]) ? (float) $valsamount[$status] : 0), 0, '', 1, -1, -1, $conf->currency).' | ';
$stringtoprint .= "
\n";
}
}
@@ -277,7 +277,7 @@ class box_funnel_of_prospection extends ModeleBoxes
);
$this->info_box_contents[$line][] = array(
'tr' => 'class="oddeven"',
- 'td' => 'class="right "',
+ 'td' => 'class="nowraponall right amount"',
'maxlength' => 500,
'text' => price($totalamount, 0, '', 1, -1, -1, $conf->currency)
);
@@ -290,7 +290,7 @@ class box_funnel_of_prospection extends ModeleBoxes
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="right "',
+ 'td' => 'class="nowraponall right amount"',
'maxlength' => 500,
'text' => price(price2num($ponderated_opp_amount, 'MT'), 0, '', 1, -1, -1, $conf->currency)
);
diff --git a/htdocs/core/boxes/box_members_last_subscriptions.php b/htdocs/core/boxes/box_members_last_subscriptions.php
index 949edd567f3..930b4d3a874 100644
--- a/htdocs/core/boxes/box_members_last_subscriptions.php
+++ b/htdocs/core/boxes/box_members_last_subscriptions.php
@@ -152,8 +152,8 @@ class box_members_last_subscriptions extends ModeleBoxes
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="right" width="18"',
- 'text' => '
'.price($obj->subscription).'',
+ 'td' => 'class="nowraponall right amount" width="18"',
+ 'text' => price($obj->subscription),
);
$this->info_box_contents[$line][] = array(
diff --git a/htdocs/core/boxes/box_members_subscriptions_by_year.php b/htdocs/core/boxes/box_members_subscriptions_by_year.php
index 73c71521603..e7bf916d236 100644
--- a/htdocs/core/boxes/box_members_subscriptions_by_year.php
+++ b/htdocs/core/boxes/box_members_subscriptions_by_year.php
@@ -179,12 +179,12 @@ class box_members_subscriptions_by_year extends ModeleBoxes
'text' => $Number[$key],
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="right"',
- 'text' => '
'.price($value).'',
+ 'td' => 'class="nowraponall right amount"',
+ 'text' => price($value),
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="right"',
- 'text' => '
'.price(price2num($value / $Number[$key], 'MT')).'',
+ 'td' => 'class="nowraponall right amount"',
+ 'text' => price(price2num($value / $Number[$key], 'MT')),
);
$line++;
}
@@ -204,12 +204,12 @@ class box_members_subscriptions_by_year extends ModeleBoxes
'text' => $numb,
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="liste_total right"',
- 'text' => '
'.price($tot).'',
+ 'td' => 'class="liste_total nowraponall right amount"',
+ 'text' => price($tot),
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="liste_total right"',
- 'text' => '
'.price(price2num($numb > 0 ? ($tot / $numb) : 0, 'MT')).'',
+ 'td' => 'class="liste_total nowraponall right amount"',
+ 'text' => price(price2num($numb > 0 ? ($tot / $numb) : 0, 'MT')),
);
}
} else {
diff --git a/htdocs/core/boxes/box_produits.php b/htdocs/core/boxes/box_produits.php
index d039881445e..9a0c76503d0 100644
--- a/htdocs/core/boxes/box_produits.php
+++ b/htdocs/core/boxes/box_produits.php
@@ -180,7 +180,7 @@ class box_produits extends ModeleBoxes
}
}
$this->info_box_contents[$line][] = array(
- 'td' => 'class="right"',
+ 'td' => 'class="nowraponall right amount"',
'text' => $price,
);
diff --git a/htdocs/core/boxes/box_produits_alerte_stock.php b/htdocs/core/boxes/box_produits_alerte_stock.php
index 5e7ec72d0e1..e074cb76198 100644
--- a/htdocs/core/boxes/box_produits_alerte_stock.php
+++ b/htdocs/core/boxes/box_produits_alerte_stock.php
@@ -94,12 +94,12 @@ class box_produits_alerte_stock extends ModeleBoxes
$sql .= " FROM ".MAIN_DB_PREFIX."product as p";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as s on p.rowid = s.fk_product";
$sql .= ' WHERE p.entity IN ('.getEntity($productstatic->element).')';
- $sql .= " AND p.tosell = 1 AND p.seuil_stock_alerte > 0";
+ $sql .= " AND p.seuil_stock_alerte > 0";
if (empty($user->rights->produit->lire)) {
- $sql .= ' AND p.fk_product_type != 0';
+ $sql .= ' AND p.fk_product_type <> 0';
}
if (empty($user->rights->service->lire)) {
- $sql .= ' AND p.fk_product_type != 1';
+ $sql .= ' AND p.fk_product_type <> 1';
}
// Add where from hooks
if (is_object($hookmanager)) {
@@ -163,7 +163,7 @@ class box_produits_alerte_stock extends ModeleBoxes
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="tdoverflowmax150 maxwidth150onsmartphone"',
+ 'td' => 'class="tdoverflowmax100 maxwidth150onsmartphone"',
'text' => $objp->label,
);
@@ -186,18 +186,13 @@ class box_produits_alerte_stock extends ModeleBoxes
}
}
- $this->info_box_contents[$line][] = array(
- 'td' => 'class="right nowraponall"',
- 'text' => $price,
- );
+ /*$this->info_box_contents[$line][] = array(
+ 'td' => 'class="nowraponall right amount"',
+ 'text' => $price.' '.$price_base_type,
+ );*/
$this->info_box_contents[$line][] = array(
- 'td' => 'class="right"',
- 'text' => $price_base_type,
- );
-
- $this->info_box_contents[$line][] = array(
- 'td' => 'class="center"',
+ 'td' => 'class="center nowraponall"',
'text' => price2num($objp->total_stock, 'MS').' / '.$objp->seuil_stock_alerte,
'text2'=>img_warning($langs->transnoentitiesnoconv("StockLowerThanLimit", $objp->seuil_stock_alerte)),
);
@@ -210,7 +205,7 @@ class box_produits_alerte_stock extends ModeleBoxes
$this->info_box_contents[$line][] = array(
'td' => 'class="right" width="18"',
- 'text' => '
'.$productstatic->LibStatut($objp->tobuy, 3, 0).'',
+ 'text' => '
'.$productstatic->LibStatut($objp->tobuy, 3, 1).'',
'asis' => 1
);
diff --git a/htdocs/core/boxes/box_propales.php b/htdocs/core/boxes/box_propales.php
index 51d313b7254..f3f9496325f 100644
--- a/htdocs/core/boxes/box_propales.php
+++ b/htdocs/core/boxes/box_propales.php
@@ -160,7 +160,7 @@ class box_propales extends ModeleBoxes
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="right nowraponall"',
+ 'td' => 'class="nowraponall right amount"',
'text' => price($objp->total_ht, 0, $langs, 0, -1, -1, $conf->currency),
);
diff --git a/htdocs/core/boxes/box_supplier_orders.php b/htdocs/core/boxes/box_supplier_orders.php
index 2cc34a9255b..89fd7850c5c 100644
--- a/htdocs/core/boxes/box_supplier_orders.php
+++ b/htdocs/core/boxes/box_supplier_orders.php
@@ -147,7 +147,7 @@ class box_supplier_orders extends ModeleBoxes
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="right nowraponall"',
+ 'td' => 'class="nowraponall right amount"',
'text' => price($objp->total_ht, 0, $langs, 0, -1, -1, $conf->currency),
);
diff --git a/htdocs/core/boxes/box_supplier_orders_awaiting_reception.php b/htdocs/core/boxes/box_supplier_orders_awaiting_reception.php
index f9d2de4b7fc..9a40c3f9aec 100644
--- a/htdocs/core/boxes/box_supplier_orders_awaiting_reception.php
+++ b/htdocs/core/boxes/box_supplier_orders_awaiting_reception.php
@@ -151,7 +151,7 @@ class box_supplier_orders_awaiting_reception extends ModeleBoxes
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="right nowraponall"',
+ 'td' => 'class="nowraponall right amount"',
'text' => price($objp->total_ht, 0, $langs, 0, -1, -1, $conf->currency),
);
diff --git a/htdocs/core/boxes/box_validated_projects.php b/htdocs/core/boxes/box_validated_projects.php
index 574ee7b7d80..e57bb1f14d9 100644
--- a/htdocs/core/boxes/box_validated_projects.php
+++ b/htdocs/core/boxes/box_validated_projects.php
@@ -26,6 +26,7 @@
*/
include_once DOL_DOCUMENT_ROOT."/core/boxes/modules_boxes.php";
+
/**
* Class to manage the box to show last projet
*/
@@ -63,7 +64,7 @@ class box_validated_projects extends ModeleBoxes
$langs->loadLangs(array('boxes', 'projects'));
$this->db = $db;
- $this->boxlabel = "ProjectsWithTask";
+ $this->boxlabel = "ProjectTasksWithoutTimeSpent";
$this->hidden = !($user->rights->projet->lire);
@@ -116,7 +117,7 @@ class box_validated_projects extends ModeleBoxes
$sql .= " INNER JOIN ".MAIN_DB_PREFIX."element_contact as ec ON ec.element_id = t.rowid AND fk_c_type_contact IN (-1, -2, -3)";
$sql .= " WHERE p.fk_statut = 1"; // Only open projects
if ($projectsListId) {
- $sql .= ' AND p.rowid IN ('.$this->db->sanitize($projectsListId).')'; // Only project are allowed
+ $sql .= ' AND p.rowid IN ('.$this->db->sanitize($projectsListId).')'; // Only projects that are allowed
}
$sql .= " AND t.rowid NOT IN (SELECT fk_task FROM ".MAIN_DB_PREFIX."projet_task_time WHERE fk_user = ".((int) $user->id).")";
$sql .= " GROUP BY p.rowid, p.ref, p.fk_soc, p.dateo";
diff --git a/htdocs/core/class/CSMSFile.class.php b/htdocs/core/class/CSMSFile.class.php
index 8d5bcf7dc50..3f082ba6d53 100644
--- a/htdocs/core/class/CSMSFile.class.php
+++ b/htdocs/core/class/CSMSFile.class.php
@@ -29,8 +29,9 @@
/**
* Class to send SMS
- * Usage: $smsfile = new CSMSFile($subject,$sendto,$replyto,$message,$filepath,$mimetype,$filename,$cc,$ccc,$deliveryreceipt,$msgishtml,$errors_to);
- * $smsfile->sendfile();
+ * Usage: $smsfile = new CSMSFile($subject,$sendto,$replyto,$message,$filepath,$mimetype,$filename,$cc,$ccc,$deliveryreceipt,$msgishtml,$errors_to);
+ * $smsfile->socid=...; $smsfile->contact_id=...; $smsfile->member_id=...; $smsfile->fk_project=...;
+ * $smsfile->sendfile();
*/
class CSMSFile
{
@@ -48,7 +49,8 @@ class CSMSFile
public $nostop;
public $socid;
- public $contactid;
+ public $contact_id;
+ public $member_id;
public $fk_project;
@@ -135,6 +137,7 @@ class CSMSFile
$sms->socid = $this->socid;
$sms->contact_id = $this->contact_id;
+ $sms->member_id = $this->member_id;
$sms->project = $this->fk_project;
$res = $sms->SmsSend();
@@ -167,6 +170,7 @@ class CSMSFile
$sms->socid = $this->socid;
$sms->contact_id = $this->contact_id;
+ $sms->member_id = $this->member_id;
$sms->fk_project = $this->fk_project;
$res = $sms->SmsSend();
diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php
index 8ce7fb24aeb..74ff2141820 100644
--- a/htdocs/core/class/commoninvoice.class.php
+++ b/htdocs/core/class/commoninvoice.class.php
@@ -811,6 +811,64 @@ abstract class CommonInvoice extends CommonObject
return -1;
}
}
+
+
+ /**
+ * Build string for ZATCA QR Code (Arabi Saudia)
+ *
+ * @return string String for ZATCA QR Code
+ */
+ public function buildZATCAQRString()
+ {
+ global $conf;
+
+ $tmplang = new Translate('', $conf);
+ $tmplang->setDefaultLang('en_US');
+ $tmplang->load("main");
+
+ $datestring = dol_print_date($this->date, 'dayhourrfc');
+ $pricewithtaxstring = price($this->total_ttc, 0, $tmplang, 0, -1, 2);
+ $pricetaxstring = price($this->total_tva, 0, $tmplang, 0, -1, 2);
+
+ /*
+ $name = implode(unpack("H*", $this->thirdparty->name));
+ $vatnumber = implode(unpack("H*", $this->thirdparty->tva_intra));
+ $date = implode(unpack("H*", $datestring));
+ $pricewithtax = implode(unpack("H*", price2num($pricewithtaxstring, 2)));
+ $pricetax = implode(unpack("H*", $pricetaxstring));
+
+ var_dump(strlen($this->thirdparty->name));
+ var_dump(str_pad(dechex('9'), 2, '0', STR_PAD_LEFT));
+ var_dump($this->thirdparty->name);
+ var_dump(implode(unpack("H*", $this->thirdparty->name)));
+ var_dump(price($this->total_tva, 0, $tmplang, 0, -1, 2));
+
+ $s = '01'.str_pad(dechex(strlen($this->thirdparty->name)), 2, '0', STR_PAD_LEFT).$name;
+ $s .= '02'.str_pad(dechex(strlen($this->thirdparty->tva_intra)), 2, '0', STR_PAD_LEFT).$vatnumber;
+ $s .= '03'.str_pad(dechex(strlen($datestring)), 2, '0', STR_PAD_LEFT).$date;
+ $s .= '04'.str_pad(dechex(strlen($pricewithtaxstring)), 2, '0', STR_PAD_LEFT).$pricewithtax;
+ $s .= '05'.str_pad(dechex(strlen($pricetaxstring)), 2, '0', STR_PAD_LEFT).$pricetax;
+ $s .= ''; // Hash of xml invoice
+ $s .= ''; // ecda signature
+ $s .= ''; // ecda public key
+ $s .= ''; // ecda signature of public key stamp
+ */
+
+ // Using TLV format
+ $s = pack('C1', 1).pack('C1', strlen($this->thirdparty->name)).$this->thirdparty->name;
+ $s .= pack('C1', 2).pack('C1', strlen($this->thirdparty->tva_intra)).$this->thirdparty->tva_intra;
+ $s .= pack('C1', 3).pack('C1', strlen($datestring)).$date;
+ $s .= pack('C1', 4).pack('C1', strlen($pricewithtaxstring)).$pricewithtaxstring;
+ $s .= pack('C1', 5).pack('C1', strlen($pricetaxstring)).$pricetaxstring;
+ $s .= ''; // Hash of xml invoice
+ $s .= ''; // ecda signature
+ $s .= ''; // ecda public key
+ $s .= ''; // ecda signature of public key stamp
+
+ $s = base64_encode($s);
+
+ return $s;
+ }
}
diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php
index 38449d1fba1..1345320f08a 100644
--- a/htdocs/core/class/commonobject.class.php
+++ b/htdocs/core/class/commonobject.class.php
@@ -1215,17 +1215,20 @@ abstract class CommonObject
public function delete_linked_contact($source = '', $code = '')
{
// phpcs:enable
+ $listId = '';
$temp = array();
$typeContact = $this->liste_type_contact($source, '', 0, 0, $code);
- foreach ($typeContact as $key => $value) {
- array_push($temp, $key);
+ if (!empty($typeContact)) {
+ foreach ($typeContact as $key => $value) {
+ array_push($temp, $key);
+ }
+ $listId = implode(",", $temp);
}
- $listId = implode(",", $temp);
$sql = "DELETE FROM ".MAIN_DB_PREFIX."element_contact";
$sql .= " WHERE element_id = ".((int) $this->id);
- if ($listId) {
+ if (!empty($listId)) {
$sql .= " AND fk_c_type_contact IN (".$this->db->sanitize($listId).")";
}
@@ -3694,23 +3697,23 @@ abstract class CommonObject
/**
* Fetch array of objects linked to current object (object of enabled modules only). Links are loaded into
* this->linkedObjectsIds array +
- * this->linkedObjects array if $loadalsoobjects = 1
+ * this->linkedObjects array if $loadalsoobjects = 1 or $loadalsoobjects = type
* Possible usage for parameters:
* - all parameters empty -> we look all link to current object (current object can be source or target)
- * - source id+type -> will get target list linked to source
- * - target id+type -> will get source list linked to target
- * - source id+type + target type -> will get target list of the type
- * - target id+type + target source -> will get source list of the type
+ * - source id+type -> will get list of targets linked to source
+ * - target id+type -> will get list of sources linked to target
+ * - source id+type + target type -> will get list of targets of the type linked to source
+ * - target id+type + source type -> will get list of sources of the type linked to target
*
- * @param int $sourceid Object source id (if not defined, id of object)
- * @param string $sourcetype Object source type (if not defined, element name of object)
- * @param int $targetid Object target id (if not defined, id of object)
- * @param string $targettype Object target type (if not defined, elemennt name of object)
- * @param string $clause 'OR' or 'AND' clause used when both source id and target id are provided
- * @param int $alsosametype 0=Return only links to object that differs from source type. 1=Include also link to objects of same type.
- * @param string $orderby SQL 'ORDER BY' clause
- * @param int $loadalsoobjects Load also array this->linkedObjects (Use 0 to increase performances)
- * @return int <0 if KO, >0 if OK
+ * @param int $sourceid Object source id (if not defined, id of object)
+ * @param string $sourcetype Object source type (if not defined, element name of object)
+ * @param int $targetid Object target id (if not defined, id of object)
+ * @param string $targettype Object target type (if not defined, element name of object)
+ * @param string $clause 'OR' or 'AND' clause used when both source id and target id are provided
+ * @param int $alsosametype 0=Return only links to object that differs from source type. 1=Include also link to objects of same type.
+ * @param string $orderby SQL 'ORDER BY' clause
+ * @param int|string $loadalsoobjects Load also array this->linkedObjects. Use 0 to increase performances, Use 1 to load all, Use value of type ('facture', 'facturerec', ...) to load only a type of object.
+ * @return int <0 if KO, >0 if OK
* @see add_object_linked(), updateObjectLinked(), deleteObjectLinked()
*/
public function fetchObjectLinked($sourceid = null, $sourcetype = '', $targetid = null, $targettype = '', $clause = 'OR', $alsosametype = 1, $orderby = 'sourcetype', $loadalsoobjects = 1)
@@ -3892,10 +3895,9 @@ abstract class CommonObject
$module = 'mrp';
}
-
- // Here $module, $classfile and $classname are set
+ // Here $module, $classfile and $classname are set, we can use them.
if ($conf->$module->enabled && (($element != $this->element) || $alsosametype)) {
- if ($loadalsoobjects) {
+ if ($loadalsoobjects && (is_numeric($loadalsoobjects) || ($loadalsoobjects === $objecttype))) {
dol_include_once('/'.$classpath.'/'.$classfile.'.class.php');
//print '/'.$classpath.'/'.$classfile.'.class.php '.class_exists($classname);
if (class_exists($classname)) {
@@ -5292,103 +5294,14 @@ abstract class CommonObject
// Index file in database
if (!empty($obj->result['fullpath'])) {
$destfull = $obj->result['fullpath'];
- $upload_dir = dirname($destfull);
- $destfile = basename($destfull);
- $rel_dir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $upload_dir);
- if (!preg_match('/[\\/]temp[\\/]|[\\/]thumbs|\.meta$/', $rel_dir)) { // If not a tmp dir
- $filename = basename($destfile);
- $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
- $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
-
- include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
- $ecmfile = new EcmFiles($this->db);
- $result = $ecmfile->fetch(0, '', ($rel_dir ? $rel_dir.'/' : '').$filename);
-
- // Set the public "share" key
- $setsharekey = false;
- if ($this->element == 'propal') {
- $useonlinesignature = 1; // Replace this with 1 when feature to make online signature is ok
- if ($useonlinesignature) {
- $setsharekey = true;
- }
- if (!empty($conf->global->PROPOSAL_ALLOW_EXTERNAL_DOWNLOAD)) {
- $setsharekey = true;
- }
- }
- if ($this->element == 'commande' && !empty($conf->global->ORDER_ALLOW_EXTERNAL_DOWNLOAD)) {
- $setsharekey = true;
- }
- if ($this->element == 'facture' && !empty($conf->global->INVOICE_ALLOW_EXTERNAL_DOWNLOAD)) {
- $setsharekey = true;
- }
- if ($this->element == 'bank_account' && !empty($conf->global->BANK_ACCOUNT_ALLOW_EXTERNAL_DOWNLOAD)) {
- $setsharekey = true;
- }
- if ($this->element == 'contrat' && !empty($conf->global->CONTRACT_ALLOW_EXTERNAL_DOWNLOAD)) {
- $setsharekey = true;
- }
- if ($this->element == 'supplier_proposal' && !empty($conf->global->SUPPLIER_PROPOSAL_ALLOW_EXTERNAL_DOWNLOAD)) {
- $setsharekey = true;
- }
-
- if ($setsharekey) {
- if (empty($ecmfile->share)) { // Because object not found or share not set yet
- require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
- $ecmfile->share = getRandomPassword(true);
- }
- }
-
- if ($result > 0) {
- $ecmfile->label = md5_file(dol_osencode($destfull)); // hash of file content
- $ecmfile->fullpath_orig = '';
- $ecmfile->gen_or_uploaded = 'generated';
- $ecmfile->description = ''; // indexed content
- $ecmfile->keywords = ''; // keyword content
- $result = $ecmfile->update($user);
- if ($result < 0) {
- setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
- }
- } else {
- $ecmfile->entity = $conf->entity;
- $ecmfile->filepath = $rel_dir;
- $ecmfile->filename = $filename;
- $ecmfile->label = md5_file(dol_osencode($destfull)); // hash of file content
- $ecmfile->fullpath_orig = '';
- $ecmfile->gen_or_uploaded = 'generated';
- $ecmfile->description = ''; // indexed content
- $ecmfile->keywords = ''; // keyword content
- $ecmfile->src_object_type = $this->table_element; // $this->table_name is 'myobject' or 'mymodule_myobject'.
- $ecmfile->src_object_id = $this->id;
-
- $result = $ecmfile->create($user);
- if ($result < 0) {
- setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
- }
- }
-
- /*$this->result['fullname']=$destfull;
- $this->result['filepath']=$ecmfile->filepath;
- $this->result['filename']=$ecmfile->filename;*/
- //var_dump($obj->update_main_doc_field);exit;
-
- // Update the last_main_doc field into main object (if document generator has property ->update_main_doc_field set)
- $update_main_doc_field = 0;
- if (!empty($obj->update_main_doc_field)) {
- $update_main_doc_field = 1;
- }
- if ($update_main_doc_field && !empty($this->table_element)) {
- $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET last_main_doc = '".$this->db->escape($ecmfile->filepath."/".$ecmfile->filename)."'";
- $sql .= " WHERE rowid = ".((int) $this->id);
-
- $resql = $this->db->query($sql);
- if (!$resql) {
- dol_print_error($this->db);
- } else {
- $this->last_main_doc = $ecmfile->filepath.'/'.$ecmfile->filename;
- }
- }
+ // Update the last_main_doc field into main object (if document generator has property ->update_main_doc_field set)
+ $update_main_doc_field = 0;
+ if (!empty($obj->update_main_doc_field)) {
+ $update_main_doc_field = 1;
}
+
+ $this->indexFile($destfull, $update_main_doc_field);
} else {
dol_syslog('Method ->write_file was called on object '.get_class($obj).' and return a success but the return array ->result["fullpath"] was not set.', LOG_WARNING);
}
@@ -5417,6 +5330,115 @@ abstract class CommonObject
}
}
+ /**
+ * Index a file into the ECM database
+ *
+ * @param string $destfull Full path of file to index
+ * @param int $update_main_doc_field Update field main_doc file into table of object
+ * @return int <0 if KO, >0 if OK
+ */
+ public function indexFile($destfull, $update_main_doc_field)
+ {
+ global $conf, $user;
+
+ $upload_dir = dirname($destfull);
+ $destfile = basename($destfull);
+ $rel_dir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $upload_dir);
+
+ if (!preg_match('/[\\/]temp[\\/]|[\\/]thumbs|\.meta$/', $rel_dir)) { // If not a tmp dir
+ $filename = basename($destfile);
+ $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
+ $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
+
+ include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
+ $ecmfile = new EcmFiles($this->db);
+ $result = $ecmfile->fetch(0, '', ($rel_dir ? $rel_dir.'/' : '').$filename);
+
+ // Set the public "share" key
+ $setsharekey = false;
+ if ($this->element == 'propal' || $this->element == 'proposal') {
+ if (!isset($conf->global->PROPOSAL_ALLOW_ONLINESIGN) || !empty($conf->global->PROPOSAL_ALLOW_ONLINESIGN)) {
+ $setsharekey = true; // feature to make online signature is not set or set to on (default)
+ }
+ if (!empty($conf->global->PROPOSAL_ALLOW_EXTERNAL_DOWNLOAD)) {
+ $setsharekey = true;
+ }
+ }
+ if ($this->element == 'commande' && !empty($conf->global->ORDER_ALLOW_EXTERNAL_DOWNLOAD)) {
+ $setsharekey = true;
+ }
+ if ($this->element == 'facture' && !empty($conf->global->INVOICE_ALLOW_EXTERNAL_DOWNLOAD)) {
+ $setsharekey = true;
+ }
+ if ($this->element == 'bank_account' && !empty($conf->global->BANK_ACCOUNT_ALLOW_EXTERNAL_DOWNLOAD)) {
+ $setsharekey = true;
+ }
+ if ($this->element == 'contrat' && !empty($conf->global->CONTRACT_ALLOW_EXTERNAL_DOWNLOAD)) {
+ $setsharekey = true;
+ }
+ if ($this->element == 'supplier_proposal' && !empty($conf->global->SUPPLIER_PROPOSAL_ALLOW_EXTERNAL_DOWNLOAD)) {
+ $setsharekey = true;
+ }
+
+ if ($setsharekey) {
+ if (empty($ecmfile->share)) { // Because object not found or share not set yet
+ require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
+ $ecmfile->share = getRandomPassword(true);
+ }
+ }
+
+ if ($result > 0) {
+ $ecmfile->label = md5_file(dol_osencode($destfull)); // hash of file content
+ $ecmfile->fullpath_orig = '';
+ $ecmfile->gen_or_uploaded = 'generated';
+ $ecmfile->description = ''; // indexed content
+ $ecmfile->keywords = ''; // keyword content
+ $result = $ecmfile->update($user);
+ if ($result < 0) {
+ setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
+ return -1;
+ }
+ } else {
+ $ecmfile->entity = $conf->entity;
+ $ecmfile->filepath = $rel_dir;
+ $ecmfile->filename = $filename;
+ $ecmfile->label = md5_file(dol_osencode($destfull)); // hash of file content
+ $ecmfile->fullpath_orig = '';
+ $ecmfile->gen_or_uploaded = 'generated';
+ $ecmfile->description = ''; // indexed content
+ $ecmfile->keywords = ''; // keyword content
+ $ecmfile->src_object_type = $this->table_element; // $this->table_name is 'myobject' or 'mymodule_myobject'.
+ $ecmfile->src_object_id = $this->id;
+
+ $result = $ecmfile->create($user);
+ if ($result < 0) {
+ setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
+ return -1;
+ }
+ }
+
+ /*$this->result['fullname']=$destfull;
+ $this->result['filepath']=$ecmfile->filepath;
+ $this->result['filename']=$ecmfile->filename;*/
+ //var_dump($obj->update_main_doc_field);exit;
+
+ if ($update_main_doc_field && !empty($this->table_element)) {
+ $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET last_main_doc = '".$this->db->escape($ecmfile->filepath."/".$ecmfile->filename)."'";
+ $sql .= " WHERE rowid = ".((int) $this->id);
+
+ $resql = $this->db->query($sql);
+ if (!$resql) {
+ dol_print_error($this->db);
+ return -1;
+ } else {
+ $this->last_main_doc = $ecmfile->filepath.'/'.$ecmfile->filename;
+ }
+ }
+ }
+
+ return 1;
+ }
+
/**
* Build thumb
* @todo Move this into files.lib.php
@@ -6090,6 +6112,7 @@ abstract class CommonObject
}
$sql .= ")";
+
$resql = $this->db->query($sql);
if (!$resql) {
$this->error = $this->db->lasterror();
@@ -7575,7 +7598,7 @@ abstract class CommonObject
} else { return true; }
} elseif (in_array($type, array('double', 'real', 'price'))) {
// is numeric
- if (!$validate->isDuration($fieldValue)) {
+ if (!$validate->isNumeric($fieldValue)) {
$this->setFieldError($fieldKey, $validate->error);
return false;
} else { return true; }
@@ -7615,7 +7638,7 @@ abstract class CommonObject
$selectkey = $InfoFieldList[2];
}
- if (!isInDb($value_arr, $InfoFieldList[0], $selectkey)) {
+ if (!$validate->isInDb($value_arr, $InfoFieldList[0], $selectkey)) {
$this->setFieldError($fieldKey, $validate->error);
return false;
} else { return true; }
@@ -7766,7 +7789,8 @@ abstract class CommonObject
}
}
- $out .= $extrafields->showSeparator($key, $this, ($colspan + 1), $display_type);
+ // if colspan=0 or 1, the second column is not extended, so the separator must be on 2 columns
+ $out .= $extrafields->showSeparator($key, $this, ($colspan ? $colspan + 1 : 2), $display_type);
} else {
$class = (!empty($extrafields->attributes[$this->table_element]['hidden'][$key]) ? 'hideobject ' : '');
$csstyle = '';
@@ -7865,6 +7889,7 @@ abstract class CommonObject
$html_id = !empty($this->id) ? $this->element.'_extras_'.$key.'_'.$this->id : '';
if ($display_type == 'card') {
+ // a first td column was already output (and may be another on before if MAIN_VIEW_LINE_NUMBER set), so this td is the next one
$out .= '