diff --git a/ChangeLog b/ChangeLog index fea73254f20..3b81e0555d5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -380,6 +380,77 @@ Following changes may create regressions for some external modules, but were nec * The jquery plugin/dependency multiselect has been removed. It was not used by Dolibarr core. +***** ChangeLog for 10.0.7 compared to 10.0.6 ***** +FIX: 10.0 - missing translations for "orders" homepage "orders" box +FIX: 10.0 - status missing from last customer invoices box when using MAIN_STATUS_USES_CSS +FIX: 10.0 - translations for "orders" not loaded in the homepage box +FIX: #10309 +FIX: #12875 +FIX: #12932 +FIX: #12966 +FIX: #12973 +FIX: #13304 +FIX: advanced target emailing sql and ergonomy +FIX: an external user can not approved +FIX: Bad translation for productlot EatBy and SellBy +FIX: better check +FIX: better method to check user rights AND usergroup rights ! +FIX: CA by prod list filter +FIX: can be a string or integer +FIX: Check on unicity on prof id was not triggered sometimes +FIX: clone of purchase order +FIX: compatibility with multicompany (avoid duplicate data) +FIX: complex export model loading +FIX: date filter not used if no operator +FIX: date order was -1D and desc with label repetition +FIX: default lang selection when filter +FIX: dom and missing param +FIX: drafts are now implemented for stats +FIX: Error in log for email sending with smtps was not complete +FIX: Extrafield position in export field list must respect "pos" field +FIX: FEC export format +FIX: FEC export have specific name +FIX: fetching account on current entity +FIX: Filenames must not contains non ascii char or we will get non ascii +FIX: fk_type subscription list via api REST +FIX: Force FEC export to txt format +FIX: get remain to pay with rounding decimals +FIX: Invert isSellerInEEC and isBuyerInEEC +FIX: keep assigned users in session when loading projects and tasks +FIX: length, width and height units coherence in product table +FIX: links in products/services index +FIX: Mail smtps truncated if content has a line with single . +FIX: missing array option +FIX: missing global $conf +FIX: missing hook parameter +FIX: Missing Linked objects Fichinter Ref. in PDF formats +FIX: missing "statut" for getNomUrl() function +FIX: multicompany for discount +FIX: must be == and not = +FIX: Problem with column label in subscription list +FIX: regex for include or exclude categories in full arbo +FIX: Remove unexisting link +FIX: remove unused var, $usercancreate can be change by Multicompany +FIX: require category class in extrafield +FIX: round MT in accountancy books +FIX: search with '0' +FIX: send expense report mail in HTML format +FIX: SQL request and phpunit +FIX: substitute lines dates values on doc generator (ODT, ...) +FIX: test on 0 better than isset +FIX: The "automatic bind" was linked EEC to export accountancy code +FIX: thirdparty alias name desappeared if we change country with THIRDPARTY_SUGGEST_ALSO_ADDRESS_CREATION conf +FIX: timezone must be tzserver and not tzuser as well as on contract card +FIX: typo on ckeck method +FIX: use "usergroup" instead "user" +FIX: Visualization rights correction on last modified contacts box +FIX: Warning on admin/export_files +FIX: We want to be able to import data for extrafields of entity 0 too +FIX: when we filter a list on a view status, we want this filter to be on bookmark that we create +FIX: wrong test +FIX: XSS vulnerability in description of list of audit events. +FIX: z-index for moretabsList with constant MAIN_MAXTABS_IN_CARD + ***** ChangeLog for 10.0.6 compared to 10.0.5 ***** FIX Regression of 10.0.5 to create/edit proposals and orders. FIX: #12760 #12763 #12755 #12765 #12751 diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php index 7497ededc8f..c9b7ee42fcf 100644 --- a/htdocs/adherents/list.php +++ b/htdocs/adherents/list.php @@ -52,6 +52,7 @@ $search_lastname = GETPOST("search_lastname", 'alpha'); $search_firstname = GETPOST("search_firstname", 'alpha'); $search_gender = GETPOST("search_gender", 'alpha'); $search_civility = GETPOST("search_civility", 'alpha'); +$search_company = GETPOST('search_company', 'alphanohtml'); $search_login = GETPOST("search_login", 'alpha'); $search_address = GETPOST("search_address", 'alpha'); $search_zip = GETPOST("search_zip", 'alpha'); @@ -254,6 +255,7 @@ $sql = "SELECT d.rowid, d.login, d.lastname, d.firstname, d.gender, d.societe as $sql .= " d.civility, d.datefin, d.address, d.zip, d.town, d.state_id, d.country,"; $sql .= " d.email, d.phone, d.phone_perso, d.phone_mobile, d.skype, d.birth, d.public, d.photo,"; $sql .= " d.fk_adherent_type as type_id, d.morphy, d.statut, d.datec as date_creation, d.tms as date_update,"; +$sql .= " s.nom,"; $sql .= " t.libelle as type, t.subscription,"; $sql .= " state.code_departement as state_code, state.nom as state_name,"; // Add fields from extrafields @@ -269,6 +271,7 @@ if (is_array($extrafields->attributes[$object->table_element]['label']) && count if (!empty($search_categ) || !empty($catid)) $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX."categorie_member as cm ON d.rowid = cm.fk_member"; // We need this table joined to the select in order to filter by categ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as country on (country.rowid = d.country)"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as state on (state.rowid = d.state_id)"; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on (s.rowid = d.fk_soc)"; $sql .= ", ".MAIN_DB_PREFIX."adherent_type as t"; $sql .= " WHERE d.fk_adherent_type = t.rowid "; if ($catid > 0) $sql .= " AND cm.fk_categorie = ".$db->escape($catid); @@ -289,6 +292,7 @@ if ($search_firstname) $sql .= natural_search("d.firstname", $search_firstname); if ($search_lastname) $sql .= natural_search(array("d.firstname", "d.lastname", "d.societe"), $search_lastname); if ($search_gender != '' && $search_gender != '-1') $sql .= " AND d.gender = '".$search_gender."'"; if ($search_login) $sql .= natural_search("d.login", $search_login); +if ($search_company) $sql .= natural_search("s.nom", $search_company); if ($search_email) $sql .= natural_search("d.email", $search_email); if ($search_town) $sql .= natural_search("d.town", $search_town); if ($search_zip) $sql .= natural_search("d.zip", $search_zip); diff --git a/htdocs/adherents/subscription/list.php b/htdocs/adherents/subscription/list.php index f6a2871a5c0..a582584ae7f 100644 --- a/htdocs/adherents/subscription/list.php +++ b/htdocs/adherents/subscription/list.php @@ -33,6 +33,7 @@ $langs->loadLangs(array("members", "companies")); $action = GETPOST('action', 'aZ09'); $massaction = GETPOST('massaction', 'alpha'); +$contextpage = GETPOST('contextpage', 'aZ09'); $confirm = GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); @@ -116,7 +117,6 @@ if (empty($reshook)) // Purge search criteria if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) // All tests are required to be compatible with all browsers { - $search = ""; $search_type = ""; $search_ref = ""; $search_lastname = ""; @@ -338,7 +338,7 @@ if (!empty($arrayfields['t.libelle']['checked'])) if (!empty($arrayfields['d.bank']['checked'])) { print ''; - $form->select_comptes($search_account, 'search_account', 0, '', 1); + $form->select_comptes($search_account, 'search_account', 0, '', 1, '', 0, 'maxwidth150'); print ''; } @@ -446,7 +446,7 @@ while ($i < min($num, $limit)) // Type if (!empty($arrayfields['d.fk_type']['checked'])) { - print ''; + print ''; if ($typeid > 0) { print $adht->getNomUrl(1); @@ -466,14 +466,14 @@ while ($i < min($num, $limit)) // Firstname if (!empty($arrayfields['d.firstname']['checked'])) { - print ''.$adherent->firstname.''; + print ''.$adherent->firstname.''; if (!$i) $totalarray['nbfield']++; } // Login if (!empty($arrayfields['d.login']['checked'])) { - print ''.$adherent->login.''; + print ''.$adherent->login.''; if (!$i) $totalarray['nbfield']++; } @@ -489,7 +489,7 @@ while ($i < min($num, $limit)) // Banque if (!empty($arrayfields['d.bank']['checked'])) { - print ""; + print ''; if ($obj->fk_account > 0) { $accountstatic->id = $obj->fk_account; diff --git a/htdocs/admin/defaultvalues.php b/htdocs/admin/defaultvalues.php index d6981448ea6..0d9775e0fbd 100644 --- a/htdocs/admin/defaultvalues.php +++ b/htdocs/admin/defaultvalues.php @@ -38,6 +38,7 @@ if (!$user->admin) accessforbidden(); $id = GETPOST('rowid', 'int'); $action = GETPOST('action', 'alpha'); +$optioncss = GETPOST('optionscss', 'alphanohtml'); $mode = GETPOST('mode', 'aZ09') ?GETPOST('mode', 'aZ09') : 'createform'; // 'createform', 'filters', 'sortorder', 'focus' @@ -212,10 +213,10 @@ print "
\n"; if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param .= '&contextpage='.urlencode($contextpage); if ($limit > 0 && $limit != $conf->liste_limit) $param .= '&limit='.urlencode($limit); -if ($optioncss != '') $param .= '&optioncss='.urlencode($optioncss); -if ($defaulturl) $param .= '&defaulturl='.urlencode($defaulturl); -if ($defaultkey) $param .= '&defaultkey='.urlencode($defaultkey); -if ($defaultvalue) $param .= '&defaultvalue='.urlencode($defaultvalue); +if ($optioncss != '') $param .= '&optioncss='.urlencode($optioncss); +if ($defaulturl) $param .= '&defaulturl='.urlencode($defaulturl); +if ($defaultkey) $param .= '&defaultkey='.urlencode($defaultkey); +if ($defaultvalue) $param .= '&defaultvalue='.urlencode($defaultvalue); print '
entity) && $debug) ? '?debug=1' : '').'" method="POST">'; @@ -252,7 +253,7 @@ $texthelp = $langs->trans("PageUrlForDefaultValues"); if ($mode == 'createform') $texthelp .= $langs->trans("PageUrlForDefaultValuesCreate", 'societe/card.php', 'societe/card.php?abc=val1&def=val2'); else $texthelp .= $langs->trans("PageUrlForDefaultValuesList", 'societe/list.php', 'societe/list.php?abc=val1&def=val2'); $texthelp .= '

'.$langs->trans("AlsoDefaultValuesAreEffectiveForActionCreate"); -$texturl = $form->textwithpicto($langs->trans("Url"), $texthelp); +$texturl = $form->textwithpicto($langs->trans("RelativeURL"), $texthelp); print_liste_field_titre($texturl, $_SERVER["PHP_SELF"], 'page,param', '', $param, '', $sortfield, $sortorder); // Field $texthelp = $langs->trans("TheKeyIsTheNameOfHtmlField"); diff --git a/htdocs/admin/mails.php b/htdocs/admin/mails.php index 5275b77fa14..00d954883f9 100644 --- a/htdocs/admin/mails.php +++ b/htdocs/admin/mails.php @@ -99,6 +99,7 @@ $triggersendname = ''; // Disable triggers $paramname = 'id'; $mode = 'emailfortest'; $trackid = (($action == 'testhtml') ? "testhtml" : "test"); +$sendcontext=''; include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php'; if ($action == 'presend' && GETPOST('trackid', 'alphanohtml') == 'test') $action = 'test'; @@ -791,7 +792,7 @@ else print load_fiche_titre($langs->trans("DoTestServerAvailability")); include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; - $mail = new CMailFile('', '', '', ''); + $mail = new CMailFile('', '', '', '', array(), array(), array(), '', '', 0, '', '', '', '', $trackid, $sendcontext); $result = $mail->check_server_port($server, $port); if ($result) print '
'.$langs->trans("ServerAvailableOnIPOrPort", $server, $port).'
'; else diff --git a/htdocs/admin/mails_emailing.php b/htdocs/admin/mails_emailing.php index 60de9f34443..94b9bb4b83f 100644 --- a/htdocs/admin/mails_emailing.php +++ b/htdocs/admin/mails_emailing.php @@ -535,8 +535,9 @@ else print load_fiche_titre($langs->trans("DoTestServerAvailability")); include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; - $mail = new CMailFile('', '', '', ''); - $result=$mail->check_server_port($server, $port); + $mail = new CMailFile('', '', '', '', array(), array(), array(), '', '', 0, '', '', '', '', $trackid, $sendcontext); + + $result = $mail->check_server_port($server, $port); if ($result) print '
'.$langs->trans("ServerAvailableOnIPOrPort", $server, $port).'
'; else { diff --git a/htdocs/categories/class/api_categories.class.php b/htdocs/categories/class/api_categories.class.php index 459b61ba740..4274dd37344 100644 --- a/htdocs/categories/class/api_categories.class.php +++ b/htdocs/categories/class/api_categories.class.php @@ -226,7 +226,7 @@ class Categories extends DolibarrApi throw new RestException(404, 'category not found'); } - if (!DolibarrApi::_checkAccessToResource('category', $this->category->id)) { + if (!DolibarrApi::_checkAccessToResource('categorie', $this->category->id)) { throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } @@ -261,7 +261,7 @@ class Categories extends DolibarrApi throw new RestException(404, 'category not found'); } - if (!DolibarrApi::_checkAccessToResource('category', $this->category->id)) { + if (!DolibarrApi::_checkAccessToResource('categorie', $this->category->id)) { throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } @@ -750,7 +750,7 @@ class Categories extends DolibarrApi throw new RestException(404, 'category not found'); } - if (!DolibarrApi::_checkAccessToResource('category', $this->category->id)) { + if (!DolibarrApi::_checkAccessToResource('categorie', $this->category->id)) { throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } diff --git a/htdocs/categories/class/categorie.class.php b/htdocs/categories/class/categorie.class.php index 9540c2b84cd..77d6718ed17 100644 --- a/htdocs/categories/class/categorie.class.php +++ b/htdocs/categories/class/categorie.class.php @@ -966,6 +966,7 @@ class Categorie extends CommonObject // phpcs:enable $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."categorie"; $sql .= " WHERE fk_parent = ".$this->id; + $sql .= " AND entity IN (".getEntity('category').")"; $res = $this->db->query($sql); if ($res) diff --git a/htdocs/comm/mailing/card.php b/htdocs/comm/mailing/card.php index a21ea9d7d0a..e4e4237db05 100644 --- a/htdocs/comm/mailing/card.php +++ b/htdocs/comm/mailing/card.php @@ -90,13 +90,13 @@ if (empty($reshook)) // Action clone object if ($action == 'confirm_clone' && $confirm == 'yes') { - if (empty($_REQUEST["clone_content"]) && empty($_REQUEST["clone_receivers"])) + if (! GETPOST("clone_content", 'alpha') && ! GETPOST("clone_receivers", 'alpha')) { setEventMessages($langs->trans("NoCloneOptionsSpecified"), null, 'errors'); } else { - $result = $object->createFromClone($user, $object->id, $_REQUEST["clone_content"], $_REQUEST["clone_receivers"]); + $result = $object->createFromClone($user, $object->id, GETPOST("clone_content", 'alpha'), GETPOST("clone_receivers", 'alpha')); if ($result > 0) { header("Location: ".$_SERVER['PHP_SELF'].'?id='.$result); diff --git a/htdocs/comm/mailing/class/mailing.class.php b/htdocs/comm/mailing/class/mailing.class.php index 553c5e79c15..a671db7b7f9 100644 --- a/htdocs/comm/mailing/class/mailing.class.php +++ b/htdocs/comm/mailing/class/mailing.class.php @@ -273,8 +273,8 @@ class Mailing extends CommonObject * * @param User $user User making the clone * @param int $fromid Id of object to clone - * @param int $option1 1=Copy content, 0=Forget content - * @param int $option2 Not used + * @param int $option1 1=Clone content, 0=Forget content + * @param int $option2 1=Clone recipients * @return int New id of clone */ public function createFromClone(User $user, $fromid, $option1, $option2) @@ -305,7 +305,7 @@ class Mailing extends CommonObject $object->bgcolor = ''; $object->bgimage = ''; - $object->email_from = ''; + //$object->email_from = ''; // We do not reset from email because it is a mandatory value $object->email_replyto = ''; $object->email_errorsto = ''; @@ -331,7 +331,7 @@ class Mailing extends CommonObject if (! $error) { - //Clone target + // Clone recipient targets if (!empty($option2)) { require_once DOL_DOCUMENT_ROOT .'/core/modules/mailings/modules_mailings.php'; diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 6e4d2efc742..d44e7e6d5a1 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -4409,7 +4409,7 @@ class OrderLine extends CommonOrderLine foreach ($this->errors as $errmsg) { - dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR); + dol_syslog(get_class($this)."::insert ".$errmsg, LOG_ERR); $this->error .= ($this->error ? ', '.$errmsg : $errmsg); } $this->db->rollback(); diff --git a/htdocs/compta/bank/account_statement_document.php b/htdocs/compta/bank/account_statement_document.php index bdb3ac4620e..4b1515cd2bb 100644 --- a/htdocs/compta/bank/account_statement_document.php +++ b/htdocs/compta/bank/account_statement_document.php @@ -92,12 +92,12 @@ include_once DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; * View */ +$form = new Form($db); + $title = $langs->trans("FinancialAccount").' - '.$langs->trans("Documents"); $helpurl = ""; llxHeader('', $title, $helpurl); -$form = new Form($db); - if ($id > 0 || !empty($ref)) { if ($object->fetch($id, $ref)) { $upload_dir = $conf->bank->dir_output."/".$id."/statement/".dol_sanitizeFileName($num); @@ -114,13 +114,9 @@ if ($id > 0 || !empty($ref)) { $totalsize += $file['size']; } - $morehtmlref = ''; - - $title = $langs->trans("AccountStatement").' '.$num.' - '.$langs->trans("BankAccount").' '.$object->getNomUrl(1, 'receipts'); print load_fiche_titre($title, '', ''); - print '
'; print '
'; diff --git a/htdocs/compta/facture/class/facture-rec.class.php b/htdocs/compta/facture/class/facture-rec.class.php index 5480142ec78..110f5a9cbb8 100644 --- a/htdocs/compta/facture/class/facture-rec.class.php +++ b/htdocs/compta/facture/class/facture-rec.class.php @@ -251,6 +251,23 @@ class FactureRec extends CommonInvoice { $error++; } + else { + $objectline = new FactureLigneRec($this->db); + if ($objectline->fetch($result_insert)) + { + // Extrafields + if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && method_exists($facsrc->lines[$i], 'fetch_optionals')) { + $facsrc->lines[$i]->fetch_optionals($facsrc->lines[$i]->rowid); + $objectline->array_options = $facsrc->lines[$i]->array_options; + } + + $result = $objectline->insertExtraFields(); + if ($result < 0) + { + $error++; + } + } + } } if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) // To use new linkedObjectsIds instead of old linked_objects diff --git a/htdocs/compta/stats/index.php b/htdocs/compta/stats/index.php index 684ef337fcd..ba17730831f 100644 --- a/htdocs/compta/stats/index.php +++ b/htdocs/compta/stats/index.php @@ -31,12 +31,12 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; // Load translation files required by the page $langs->loadLangs(array('compta', 'bills', 'donation', 'salaries')); -$date_startmonth = GETPOST('date_startmonth'); -$date_startday = GETPOST('date_startday'); -$date_startyear = GETPOST('date_startyear'); -$date_endmonth = GETPOST('date_endmonth'); -$date_endday = GETPOST('date_endday'); -$date_endyear = GETPOST('date_endyear'); +$date_startday = GETPOST('date_startday', 'int'); +$date_startmonth = GETPOST('date_startmonth', 'int'); +$date_startyear = GETPOST('date_startyear', 'int'); +$date_endday = GETPOST('date_endday', 'int'); +$date_endmonth = GETPOST('date_endmonth', 'int'); +$date_endyear = GETPOST('date_endyear', 'int'); $nbofyear = 4; @@ -193,15 +193,18 @@ elseif ($modecompta == "BOOKKEEPING") { $sql = "SELECT date_format(b.doc_date,'%Y-%m') as dm, sum(b.credit) as amount_ttc"; $sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as b, ".MAIN_DB_PREFIX."accounting_journal as aj"; - $sql .= " WHERE b.entity = ".$conf->entity; + $sql .= " WHERE b.entity = ".$conf->entity; // In module double party accounting, we never share entities $sql .= " AND aj.entity = ".$conf->entity; $sql .= " AND b.code_journal = aj.code AND aj.nature = 2"; // @todo currently count amount in sale journal, but we need to define a category group for turnover } $sql .= " GROUP BY dm"; $sql .= " ORDER BY dm"; +// TODO Add a filter on $date_start and $date_end to reduce quantity on data //print $sql; +$minyearmonth = $maxyearmonth = 0; + $result = $db->query($sql); if ($result) { @@ -214,7 +217,7 @@ if ($result) $cum[$obj->dm] = $obj->amount_ttc; if ($obj->amount_ttc) { - $minyearmonth = ($minyearmonth ?min($minyearmonth, $obj->dm) : $obj->dm); + $minyearmonth = ($minyearmonth ? min($minyearmonth, $obj->dm) : $obj->dm); $maxyearmonth = max($maxyearmonth, $obj->dm); } $i++; @@ -309,9 +312,17 @@ for ($mois = 1 + $nb_mois_decalage; $mois <= 12 + $nb_mois_decalage; $mois++) $mois_modulo = $mois; // ajout if ($mois > 12) {$mois_modulo = $mois - 12; } // ajout + if ($year_start == $year_end) { + if ($mois > $date_endmonth && $year_end >= $date_endyear) { + break; + } + } + print ''; + // Month print "".dol_print_date(dol_mktime(12, 0, 0, $mois_modulo, 1, 2000), "%B").""; + for ($annee = $year_start - 1; $annee <= $year_end; $annee++) // We start one year before to have data to be able to make delta { $annee_decalage = $annee; diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index 17e063244df..012e9d2d8a5 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -253,7 +253,11 @@ if (!$error && $massaction == 'confirm_presend') // Test recipient if (empty($sendto)) // For the case, no recipient were set (multi thirdparties send) { - if ($objectobj->element == 'expensereport') + if ($objectobj->element == 'societe') + { + $sendto = $objectobj->email; + } + elseif ($objectobj->element == 'expensereport') { $fuser = new User($db); $fuser->fetch($objectobj->fk_user_author); @@ -289,6 +293,10 @@ if (!$error && $massaction == 'confirm_presend') if (empty($sendto)) { + if ($objectobj->element == 'societe') { + $objectobj->thirdparty = $objectobj; // Hack so following code is comaptible when objectobj is a thirdparty + } + //print "No recipient for thirdparty ".$objectobj->thirdparty->name; $nbignored++; if (empty($thirdpartywithoutemail[$objectobj->thirdparty->id])) @@ -491,9 +499,11 @@ if (!$error && $massaction == 'confirm_presend') //var_dump($trackid);exit; //var_dump($subjectreplaced); + if (empty($sendcontext)) $sendcontext = 'standard'; + // Send mail (substitutionarray must be done just before this) require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; - $mailfile = new CMailFile($subjectreplaced, $sendto, $from, $messagereplaced, $filepath, $mimetype, $filename, $sendtocc, $sendtobcc, $deliveryreceipt, -1, '', '', $trackid); + $mailfile = new CMailFile($subjectreplaced, $sendto, $from, $messagereplaced, $filepath, $mimetype, $filename, $sendtocc, $sendtobcc, $deliveryreceipt, -1, '', '', $trackid, '', $sendcontext); if ($mailfile->error) { $resaction .= '
'.$mailfile->error.'
'; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 0d3ab9162dd..57d9db22861 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -6592,7 +6592,7 @@ abstract class CommonObject * This function is responsible to output the and according to correct number of columns received into $params['colspan'] * * @param Extrafields $extrafields Extrafield Object - * @param string $mode Show output (view) or input (edit) for extrafield + * @param string $mode Show output ('view') or input ('create' or 'edit') for extrafield * @param array $params Optional parameters. Example: array('style'=>'class="oddeven"', 'colspan'=>$colspan) * @param string $keysuffix Suffix string to add after name and id of field (can be used to avoid duplicate names) * @param string $keyprefix Prefix string to add before name and id of field (can be used to avoid duplicate names) @@ -6635,7 +6635,8 @@ abstract class CommonObject $perms = dol_eval($extrafields->attributes[$this->table_element]['perms'][$key], 1); } - if (($mode == 'create' || $mode == 'edit') && abs($visibility) != 1 && abs($visibility) != 3) continue; // <> -1 and <> 1 and <> 3 = not visible on forms, only on list + if (($mode == 'create') && abs($visibility) != 1 && abs($visibility) != 3) continue; // <> -1 and <> 1 and <> 3 = not visible on forms, only on list + elseif (($mode == 'edit') && abs($visibility) != 1 && abs($visibility) != 3 && abs($visibility) != 4) continue; // <> -1 and <> 1 and <> 3 = not visible on forms, only on list and <> 4 = not visible at the creation elseif ($mode == 'view' && empty($visibility)) continue; if (empty($perms)) continue; // Load language if required @@ -6663,9 +6664,10 @@ abstract class CommonObject case "view": $value = $this->array_options["options_".$key.$keysuffix]; break; - case "edit": - $getposttemp = GETPOST($keyprefix.'options_'.$key.$keysuffix, 'none'); // GETPOST can get value from GET, POST or setup of default values. - // GETPOST("options_" . $key) can be 'abc' or array(0=>'abc') + case "create": + case "edit": + $getposttemp = GETPOST($keyprefix.'options_'.$key.$keysuffix, 'none'); // GETPOST can get value from GET, POST or setup of default values. + // GETPOST("options_" . $key) can be 'abc' or array(0=>'abc') if (is_array($getposttemp) || $getposttemp != '' || GETPOSTISSET($keyprefix.'options_'.$key.$keysuffix)) { if (is_array($getposttemp)) { @@ -6769,7 +6771,8 @@ abstract class CommonObject case "view": $out .= $extrafields->showOutputField($key, $value); break; - case "edit": + case "create": + case "edit": $out .= $extrafields->showInputField($key, $value, '', $keysuffix, '', 0, $this->id, $this->table_element); break; } diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index cf439f210be..0938da39dcd 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -2150,7 +2150,7 @@ class ExtraFields if (in_array($key_type, array('date', 'datetime'))) { - if (! GETPOSTISSET($keysuffix."options_".$key.$keyprefix)."year") continue; // Value was not provided, we should not set it. + if (! GETPOSTISSET($keysuffix."options_".$key.$keyprefix."year")) continue; // Value was not provided, we should not set it. // Clean parameters $value_key = dol_mktime(GETPOST($keysuffix."options_".$key.$keyprefix."hour", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."min", 'int'), 0, GETPOST($keysuffix."options_".$key.$keyprefix."month", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."day", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."year", 'int')); } diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index 347b22400bd..ec9dff5f1a3 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -1508,10 +1508,10 @@ class FormFile if (!empty($addfilterfields)) { print ''; - print ''; - print ''; - print ''; - print ''; + print ''; + print ''; + print ''; + print ''; // Action column print ''; $searchpicto = $form->showFilterButtons(); diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index ecf137adb04..b688d408284 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -124,10 +124,11 @@ class FormTicket /** * Show the form to input ticket * - * @param int $withdolfichehead With dol_fiche_head - * @return void + * @param int $withdolfichehead With dol_fiche_head + * @param string $mode Mode ('create' or 'edit') + * @return void */ - public function showForm($withdolfichehead = 0) + public function showForm($withdolfichehead = 0, $mode = 'edit') { global $conf, $langs, $user, $hookmanager; @@ -414,7 +415,7 @@ class FormTicket $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $ticketstat, $this->action); // Note that $action and $object may have been modified by hook if (empty($reshook)) { - print $ticketstat->showOptionals($extrafields, 'edit'); + print $ticketstat->showOptionals($extrafields, 'create'); } print ''; diff --git a/htdocs/core/lib/admin.lib.php b/htdocs/core/lib/admin.lib.php index 2433f284a2c..42813a6cf65 100644 --- a/htdocs/core/lib/admin.lib.php +++ b/htdocs/core/lib/admin.lib.php @@ -1807,7 +1807,7 @@ function email_admin_prepare_head() if ($conf->mailing->enabled) { $head[$h][0] = DOL_URL_ROOT."/admin/mails_emailing.php"; - $head[$h][1] = $langs->trans("OutGoingEmailSetupForEmailing"); + $head[$h][1] = $langs->trans("OutGoingEmailSetupForEmailing", $langs->transnoentitiesnoconv("EMailing")); $head[$h][2] = 'common_emailing'; $h++; } diff --git a/htdocs/core/lib/bank.lib.php b/htdocs/core/lib/bank.lib.php index 6c23e324f71..da51589b8ac 100644 --- a/htdocs/core/lib/bank.lib.php +++ b/htdocs/core/lib/bank.lib.php @@ -179,7 +179,7 @@ function account_statement_prepare_head($object, $num) // Attached files require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php'; - $upload_dir = $conf->bank->dir_output."/".$object->id.'/'.dol_sanitizeFileName($num); + $upload_dir = $conf->bank->dir_output."/".$object->id.'/statement/'.dol_sanitizeFileName($num); $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$')); $nbLinks = Link::count($db, $object->element, $object->id); diff --git a/htdocs/core/lib/modulebuilder.lib.php b/htdocs/core/lib/modulebuilder.lib.php index fe5d707b10a..6ea1d949833 100644 --- a/htdocs/core/lib/modulebuilder.lib.php +++ b/htdocs/core/lib/modulebuilder.lib.php @@ -127,10 +127,10 @@ function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir = { $i++; $texttoinsert .= "\t\t'".$key."' => array('type'=>'".$val['type']."', 'label'=>'".$val['label']."',"; - $texttoinsert .= " 'enabled'=>".($val['enabled'] != '' ? $val['enabled'] : 1).","; - $texttoinsert .= " 'position'=>".($val['position'] != '' ? $val['position'] : 50).","; + $texttoinsert .= " 'enabled'=>".($val['enabled'] !== '' ? $val['enabled'] : 1).","; + $texttoinsert .= " 'position'=>".($val['position'] !== '' ? $val['position'] : 50).","; $texttoinsert .= " 'notnull'=>".(empty($val['notnull']) ? 0 : $val['notnull']).","; - $texttoinsert .= " 'visible'=>".($val['visible'] != '' ? $val['visible'] : -1).","; + $texttoinsert .= " 'visible'=>".($val['visible'] !== '' ? $val['visible'] : -1).","; if ($val['noteditable']) $texttoinsert .= " 'noteditable'=>'".$val['noteditable']."',"; if ($val['default']) $texttoinsert .= " 'default'=>'".$val['default']."',"; if ($val['index']) $texttoinsert .= " 'index'=>".$val['index'].","; diff --git a/htdocs/core/lib/report.lib.php b/htdocs/core/lib/report.lib.php index 4649abc474a..979583e8b4d 100644 --- a/htdocs/core/lib/report.lib.php +++ b/htdocs/core/lib/report.lib.php @@ -53,16 +53,17 @@ function report_header($reportname, $notused, $period, $periodlink, $description $head[$h][1] = $langs->trans("Report"); $head[$h][2] = 'report'; - print ''; + print ''."\n"; + print ''."\n"; dol_fiche_head($head, 'report'); foreach($moreparam as $key => $value) { - print ''; + print ''."\n"; } - print ''; + print '
'."\n"; $variante = ($periodlink || $exportlink); @@ -73,7 +74,7 @@ function report_header($reportname, $notused, $period, $periodlink, $description print $reportname; print ''; if ($variante) print ''; - print ''; + print ''."\n"; // Calculation mode if ($calcmode) @@ -84,7 +85,7 @@ function report_header($reportname, $notused, $period, $periodlink, $description print $calcmode; if ($variante) print ''; print ''; - print ''; + print ''."\n"; } // Ligne de la periode d'analyse du rapport @@ -94,14 +95,14 @@ function report_header($reportname, $notused, $period, $periodlink, $description if ($period) print $period; if ($variante) print ''; print ''; - print ''; + print ''."\n"; // Ligne de description print ''; print ''; print ''; if ($variante) print ''; - print ''; + print ''."\n"; // Ligne d'export print ''; @@ -110,9 +111,9 @@ function report_header($reportname, $notused, $period, $periodlink, $description print dol_print_date($builddate, 'dayhour'); print ''; if ($variante) print ''; - print ''; + print ''."\n"; - print '
'.$periodlink.'
'.$langs->trans("ReportDescription").''.$description.'
'.($exportlink ? $langs->trans("Export").': '.$exportlink : '').'
'; + print ''."\n"; dol_fiche_end(); diff --git a/htdocs/core/tpl/advtarget.tpl.php b/htdocs/core/tpl/advtarget.tpl.php index b3b6b5d1bf1..07b7744e2f8 100644 --- a/htdocs/core/tpl/advtarget.tpl.php +++ b/htdocs/core/tpl/advtarget.tpl.php @@ -263,7 +263,8 @@ if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire) { // Standard Extrafield feature if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) { - $elementtype = Societe::$table_element; + $socstatic=new Societe($db); + $elementtype = $socstatic->table_element; // fetch optionals attributes and labels dol_include_once('/core/class/extrafields.class.php'); $extrafields = new ExtraFields($db); diff --git a/htdocs/core/tpl/card_presend.tpl.php b/htdocs/core/tpl/card_presend.tpl.php index 795483b08ba..37920ed1ebc 100644 --- a/htdocs/core/tpl/card_presend.tpl.php +++ b/htdocs/core/tpl/card_presend.tpl.php @@ -219,6 +219,7 @@ if ($action == 'presend') if (!empty($origin) && !empty($origin_id)) { $element = $subelement = $origin; + $regs = array(); if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) { $element = $regs[1]; $subelement = $regs[2]; diff --git a/htdocs/core/tpl/extrafields_add.tpl.php b/htdocs/core/tpl/extrafields_add.tpl.php index 2ef606afa0b..38f1cb2b8de 100644 --- a/htdocs/core/tpl/extrafields_add.tpl.php +++ b/htdocs/core/tpl/extrafields_add.tpl.php @@ -45,7 +45,7 @@ if (empty($reshook)) { $params = array(); if (isset($tpl_context)) $params['tpl_context'] = $tpl_context; $params['cols']=$parameters['colspanvalue']; - print $object->showOptionals($extrafields, 'edit', $params); // BUG #11554 : Add context in params + print $object->showOptionals($extrafields, 'create', $params); } ?> diff --git a/htdocs/core/tpl/extrafields_view.tpl.php b/htdocs/core/tpl/extrafields_view.tpl.php index 1ef3ef07255..e6cbad245d9 100644 --- a/htdocs/core/tpl/extrafields_view.tpl.php +++ b/htdocs/core/tpl/extrafields_view.tpl.php @@ -73,7 +73,7 @@ if (empty($reshook) && is_array($extrafields->attributes[$object->table_element] //print $key.'-'.$enabled.'-'.$perms.'-'.$label.$_POST["options_" . $key].'
'."\n"; if (empty($enabled)) continue; // 0 = Never visible field - if (abs($enabled) != 1 && abs($enabled) != 3 && abs($enabled) != 5) continue; // <> -1 and <> 1 and <> 3 = not visible on forms, only on list + if (abs($enabled) != 1 && abs($enabled) != 3 && abs($enabled) != 5 && abs($enabled) != 4) continue; // <> -1 and <> 1 and <> 3 = not visible on forms, only on list <> 4 = not visible at the creation if (empty($perms)) continue; // 0 = Not visible // Load language if required diff --git a/htdocs/fourn/class/fournisseur.product.class.php b/htdocs/fourn/class/fournisseur.product.class.php index 75e5a281218..f9dcdbeee6a 100644 --- a/htdocs/fourn/class/fournisseur.product.class.php +++ b/htdocs/fourn/class/fournisseur.product.class.php @@ -432,7 +432,7 @@ class ProductFournisseur extends Product $sql .= " ".($newdefaultvatcode ? "'".$this->db->escape($newdefaultvatcode)."'" : "null").","; $sql .= " ".$newnpr.","; $sql .= $conf->entity.","; - $sql .= $delivery_time_days.","; + $sql .= ($delivery_time_days != '' ? $delivery_time_days : 'null') . ","; $sql .= (empty($supplier_reputation) ? 'NULL' : "'".$this->db->escape($supplier_reputation)."'").","; $sql .= (empty($barcode) ? 'NULL' : "'".$this->db->escape($barcode)."'").","; $sql .= (empty($fk_barcode_type) ? 'NULL' : "'".$this->db->escape($fk_barcode_type)."'"); @@ -451,7 +451,7 @@ class ProductFournisseur extends Product if (!$error && empty($conf->global->PRODUCT_PRICE_SUPPLIER_NO_LOG)) { // Add record into log table // $this->product_fourn_price_id must be set - $result = $this->logPrice($user, $now, $buyprice, $qty, $multicurrency_buyprice, $multicurrency_unitBuyPrice, $multicurrency_tx, $fk_multicurrenc, $multicurrency_code); + $result = $this->logPrice($user, $now, $buyprice, $qty, $multicurrency_buyprice, $multicurrency_unitBuyPrice, $multicurrency_tx, $fk_multicurrency, $multicurrency_code); if ($result < 0) { $error++; } diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 6309387b5fb..a9503fa2162 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -1242,7 +1242,7 @@ if (empty($reshook)) '', null, null, - array(), + $array_option, $lines[$i]->fk_unit, 0, $element, diff --git a/htdocs/install/mysql/migration/repair.sql b/htdocs/install/mysql/migration/repair.sql index 7f5e6fafe3d..4297c5f324d 100644 --- a/htdocs/install/mysql/migration/repair.sql +++ b/htdocs/install/mysql/migration/repair.sql @@ -165,6 +165,10 @@ DELETE FROM llx_product_batch WHERE qty = 0; UPDATE llx_product p SET p.stock= (SELECT SUM(ps.reel) FROM llx_product_stock ps WHERE ps.fk_product = p.rowid); +-- Fix: delete orphelins in product_association +delete from llx_product_association where fk_product_pere NOT IN (select rowid from llx_product); +delete from llx_product_association where fk_product_fils NOT IN (select rowid from llx_product); + -- Fix: delete category child with no category parent. drop table tmp_categorie; create table tmp_categorie as select * from llx_categorie; diff --git a/htdocs/install/mysql/tables/llx_adherent.sql b/htdocs/install/mysql/tables/llx_adherent.sql index cb96ab98164..1917e80c81a 100644 --- a/htdocs/install/mysql/tables/llx_adherent.sql +++ b/htdocs/install/mysql/tables/llx_adherent.sql @@ -39,7 +39,7 @@ create table llx_adherent pass_crypted varchar(128), fk_adherent_type integer NOT NULL, morphy varchar(3) NOT NULL, -- personne morale / personne physique - societe varchar(128), -- company name (should be same lenght than societe.name) + societe varchar(128), -- company name (should be same length than societe.name). No more used. fk_soc integer NULL, -- Link to third party linked to member address text, zip varchar(30), diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 3fde658960e..3d774b7afdd 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -221,6 +221,7 @@ DoliPartnersDesc=List of companies providing custom-developed modules or feature WebSiteDesc=External websites for more add-on (non-core) modules... DevelopYourModuleDesc=Some solutions to develop your own module... URL=URL +RelativeURL=Relative URL BoxesAvailable=Widgets available BoxesActivated=Widgets activated ActivateOn=Activate on diff --git a/htdocs/langs/en_US/mails.lang b/htdocs/langs/en_US/mails.lang index 8b92cef3103..7b3bfd3852a 100644 --- a/htdocs/langs/en_US/mails.lang +++ b/htdocs/langs/en_US/mails.lang @@ -164,7 +164,7 @@ NoContactWithCategoryFound=No contact/address with a category found NoContactLinkedToThirdpartieWithCategoryFound=No contact/address with a category found OutGoingEmailSetup=Outgoing email setup InGoingEmailSetup=Incoming email setup -OutGoingEmailSetupForEmailing=Outgoing email setup (for mass emailing) +OutGoingEmailSetupForEmailing=Outgoing email setup (for module %s) DefaultOutgoingEmailSetup=Default outgoing email setup Information=Information ContactsWithThirdpartyFilter=Contacts with third-party filter diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 8f8480a03cb..31e0d5a1c8d 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -174,6 +174,7 @@ SaveAndStay=Save and stay SaveAndNew=Save and new TestConnection=Test connection ToClone=Clone +ConfirmCloneAsk=Are you sure you want to clone the object %s? ConfirmClone=Choose data you want to clone: NoCloneOptionsSpecified=No data to clone defined. Of=of diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 0afcd403406..31d593926d1 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -92,6 +92,7 @@ if (empty($newmask)) // This should no happen $result = restrictedArea($user, 'modulebuilder', null); +$error = 0; /* @@ -782,12 +783,20 @@ if ($dirins && $action == 'initobject' && $module && GETPOST('createtablearray', if ($dirins && $action == 'initobject' && $module && $objectname) { + $objectname = ucfirst($objectname); + if (preg_match('/[^a-z0-9_]/i', $objectname)) { $error++; setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors'); $tabobj = 'newobject'; } + if (class_exists($objectname)) { + // TODO Add a more efficient detection. Scan disk ? + $error++; + setEventMessages($langs->trans("AnObjectWithThisClassNameAlreadyExists"), null, 'errors'); + $tabobj = 'newobject'; + } $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; $destdir = $dirins.'/'.strtolower($module); @@ -879,16 +888,31 @@ if ($dirins && $action == 'initobject' && $module && $objectname) // Edit the class 'class/'.strtolower($objectname).'.class.php' if (GETPOST('includerefgeneration', 'aZ09')) { // Replace 'visible'=>1, 'noteditable'=>0, 'default'=>'' - $arrayreplacement = array('/\'visible\'=>1,\s*\'noteditable\'=>0,\s*\'default\'=>\'\'/' => "'visible'=>4, 'noteditable'=>1, 'default'=>'(PROV)'"); + $arrayreplacement = array( + '/\'visible\'=>1,\s*\'noteditable\'=>0,\s*\'default\'=>\'\'/' => "'visible'=>4, 'noteditable'=>1, 'default'=>'(PROV)'" + ); //var_dump($arrayreplacement);exit; //var_dump($destdir.'/class/'.strtolower($objectname).'.class.php');exit; dolReplaceInFile($destdir.'/class/'.strtolower($objectname).'.class.php', $arrayreplacement, '', 0, 0, 1); + + $arrayreplacement = array( + '/\'models\' => 0,/' => '\'models\' => 1,' + ); + dolReplaceInFile($destdir.'/core/modules/mod'.$module.'.class.php', $arrayreplacement, '', 0, 0, 1); } // Edit the setup file and the card page if (GETPOST('includedocgeneration', 'aZ09')) { - // TODO - // dolReplaceInFile(); + // Replace some var init into some files + $arrayreplacement = array( + '/\$includedocgeneration = 0;/' => '$includedocgeneration = 1;' + ); + dolReplaceInFile($destdir.'/class/'.strtolower($objectname).'.class.php', $arrayreplacement, '', 0, 0, 1); + + $arrayreplacement = array( + '/\'models\' => 0,/' => '\'models\' => 1,' + ); + dolReplaceInFile($destdir.'/core/modules/mod'.$module.'.class.php', $arrayreplacement, '', 0, 0, 1); } // Scan for object class files @@ -1637,12 +1661,90 @@ $head[$h][1] = ''.$langs->trans("New $head[$h][2] = 'initmodule'; $h++; -foreach ($listofmodules as $tmpmodule => $tmpmodulearray) -{ - $head[$h][0] = $_SERVER["PHP_SELF"].'?module='.$tmpmodulearray['modulenamewithcase'].($forceddirread ? '@'.$dirread : ''); - $head[$h][1] = $tmpmodulearray['modulenamewithcase']; - $head[$h][2] = $tmpmodulearray['modulenamewithcase']; - $h++; +$linktoenabledisable = ''; +$modulestatusinfo = ''; + +if (is_array($listofmodules) && count($listofmodules) > 0) { + // Define $linktoenabledisable and $modulestatusinfo + $modulelowercase=strtolower($module); + $const_name = 'MAIN_MODULE_'.strtoupper($module); + + $param=''; + if ($tab) $param.='&tab='.urlencode($tab); + if ($module) $param.='&module='.urlencode($module); + if ($tabobj) $param.='&tabobj='.urlencode($tabobj); + + $urltomodulesetup=''.$langs->trans('Home').'-'.$langs->trans("Setup").'-'.$langs->trans("Modules").''; + if (! empty($conf->global->$const_name)) // If module is already activated + { + $linktoenabledisable.=''; + $linktoenabledisable.=img_picto($langs->trans("Activated"), 'switch_on', '', false, 0, 0, '', '', 1); + $linktoenabledisable.=''; + + $objMod = $moduleobj; + $backtourlparam = ''; + $backtourlparam .= ($backtourlparam ? '&' : '?').'module='.$module; // No urlencode here, done later + if ($tab) $backtourlparam .= ($backtourlparam ? '&' : '?').'tab='.$tab; // No urlencode here, done later + $backtourl = $_SERVER["PHP_SELF"].$backtourlparam; + + $regs = array(); + if (is_array($objMod->config_page_url)) + { + $i = 0; + foreach ($objMod->config_page_url as $page) + { + $urlpage = $page; + if ($i++) + { + $linktoenabledisable .= ' '.img_picto(ucfirst($page), "setup").''; + // print ''.ucfirst($page).' '; + } + else + { + if (preg_match('/^([^@]+)@([^@]+)$/i', $urlpage, $regs)) + { + $urltouse = dol_buildpath('/'.$regs[2].'/admin/'.$regs[1], 1); + $linktoenabledisable .= '   '.img_picto($langs->trans("Setup"), "setup", 'style="padding-right: 6px"').''; + } + else + { + $urltouse = $urlpage; + $linktoenabledisable .= '   '.img_picto($langs->trans("Setup"), "setup", 'style="padding-right: 6px"').''; + } + } + } + } + elseif (preg_match('/^([^@]+)@([^@]+)$/i', $objMod->config_page_url, $regs)) + { + $linktoenabledisable .= '   '.img_picto($langs->trans("Setup"), "setup", 'style="padding-right: 6px"').''; + } + } + else + { + $linktoenabledisable.=''; + $linktoenabledisable.=img_picto($langs->trans("ModuleIsNotActive", $urltomodulesetup), 'switch_off', '', false, 0, 0, '', 'classfortooltip', 1); + $linktoenabledisable.="\n"; + } + + if (! empty($conf->$modulelowercase->enabled)) + { + $modulestatusinfo=$form->textwithpicto('', $langs->trans("Warning").' : '.$langs->trans("ModuleIsLive"), -1, 'warning'); + } + + // Loop to show tab of each module + foreach ($listofmodules as $tmpmodule => $tmpmodulearray) + { + $head[$h][0] = $_SERVER["PHP_SELF"].'?module='.$tmpmodulearray['modulenamewithcase'].($forceddirread ? '@'.$dirread : ''); + $head[$h][1] = $tmpmodulearray['modulenamewithcase']; + $head[$h][2] = $tmpmodulearray['modulenamewithcase']; + + /*if ($tmpmodule == $modulelowercase) { + $head[$h][1] .= ' '.$modulestatusinfo; + $head[$h][1] .= ' '.$linktoenabledisable; + }*/ + + $h++; + } } $head[$h][0] = $_SERVER["PHP_SELF"].'?module=deletemodule'; @@ -1694,36 +1796,6 @@ elseif (! empty($module)) $head2 = array(); $h=0; - $modulelowercase=strtolower($module); - $const_name = 'MAIN_MODULE_'.strtoupper($module); - - $param=''; - if ($tab) $param.='&tab='.urlencode($tab); - if ($module) $param.='&module='.urlencode($module); - if ($tabobj) $param.='&tabobj='.urlencode($tabobj); - - $urltomodulesetup=''.$langs->trans('Home').'-'.$langs->trans("Setup").'-'.$langs->trans("Modules").''; - $linktoenabledisable=''; - if (! empty($conf->global->$const_name)) // If module is already activated - { - $linktoenabledisable.=''; - $linktoenabledisable.=img_picto($langs->trans("Activated"), 'switch_on', '', false, 0, 0, '', '', 1); - $linktoenabledisable.=''; - } - else - { - $linktoenabledisable.=''; - $linktoenabledisable.=img_picto($langs->trans("Disabled"), 'switch_off', '', false, 0, 0, '', '', 1); - $linktoenabledisable.="\n"; - } - if (empty($conf->$modulelowercase->enabled)) - { - $modulestatusinfo=$form->textwithpicto($langs->trans("ModuleIsNotActive", $urltomodulesetup), '', -1, 'help'); - } - else - { - $modulestatusinfo=$form->textwithpicto($langs->trans("ModuleIsLive"), $langs->trans("Warning"), -1, 'warning'); - } $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=description&module='.$module.($forceddirread?'@'.$dirread:''); $head2[$h][1] = $langs->trans("Description"); @@ -1745,16 +1817,16 @@ elseif (! empty($module)) $head2[$h][2] = 'objects'; $h++; - $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=menus&module='.$module.($forceddirread?'@'.$dirread:''); - $head2[$h][1] = $langs->trans("Menus"); - $head2[$h][2] = 'menus'; - $h++; - $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=permissions&module='.$module.($forceddirread?'@'.$dirread:''); $head2[$h][1] = $langs->trans("Permissions"); $head2[$h][2] = 'permissions'; $h++; + $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=menus&module='.$module.($forceddirread?'@'.$dirread:''); + $head2[$h][1] = $langs->trans("Menus"); + $head2[$h][2] = 'menus'; + $h++; + $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=hooks&module='.$module.($forceddirread?'@'.$dirread:''); $head2[$h][1] = $langs->trans("Hooks"); $head2[$h][2] = 'hooks'; @@ -1801,8 +1873,8 @@ elseif (! empty($module)) $h++; // Link to enable / disable - print $modulestatusinfo; - print ' '.$linktoenabledisable.'
'; + print '
'.$modulestatusinfo; + print ' '.$linktoenabledisable.'
'; print '
'; @@ -2082,7 +2154,7 @@ elseif (! empty($module)) print_liste_field_titre("Condition", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print "\n"; - if (is_array($dicts)) + if (is_array($dicts) && is_array($dicts['tabname'])) { $i = 0; $maxi = count($dicts['tabname']); @@ -2566,6 +2638,7 @@ elseif (! empty($module)) print ''; print ''; + // List of existing properties foreach ($properties as $propkey => $propval) { /* If from Reflection @@ -2637,7 +2710,7 @@ elseif (! empty($module)) print $propenabled?$propenabled:''; print ''; print ''; - print $propvisible?$propvisible:''; + print $propvisible?$propvisible:'0'; print ''; print ''; print $propnoteditable?$propnoteditable:''; diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index 596e47e12c0..97997a57542 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -551,29 +551,31 @@ class MyObject extends CommonObject } $this->newref = $num; - // Validate - $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element; - $sql .= " SET ref = '".$this->db->escape($num)."',"; - $sql .= " status = ".self::STATUS_VALIDATED.","; - $sql .= " date_validation = '".$this->db->idate($now)."',"; - $sql .= " fk_user_valid = ".$user->id; - $sql .= " WHERE rowid = ".$this->id; + if (! empty($num)) { + // Validate + $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element; + $sql .= " SET ref = '".$this->db->escape($num)."',"; + $sql .= " status = ".self::STATUS_VALIDATED; + if (! empty($this->fields['date_validation'])) $sql .= ", date_validation = '".$this->db->idate($now)."',"; + if (! empty($this->fields['fk_user_valid'])) $sql .= ", fk_user_valid = ".$user->id; + $sql .= " WHERE rowid = ".$this->id; - dol_syslog(get_class($this)."::validate()", LOG_DEBUG); - $resql = $this->db->query($sql); - if (!$resql) - { - dol_print_error($this->db); - $this->error = $this->db->lasterror(); - $error++; - } + dol_syslog(get_class($this)."::validate()", LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) + { + dol_print_error($this->db); + $this->error = $this->db->lasterror(); + $error++; + } - if (!$error && !$notrigger) - { - // Call trigger - $result = $this->call_trigger('MYOBJECT_VALIDATE', $user); - if ($result < 0) $error++; - // End call triggers + if (!$error && !$notrigger) + { + // Call trigger + $result = $this->call_trigger('MYOBJECT_VALIDATE', $user); + if ($result < 0) $error++; + // End call triggers + } } if (!$error) @@ -920,7 +922,7 @@ class MyObject extends CommonObject $langs->load("mymodule@myobject"); if (empty($conf->global->MYMODULE_MYOBJECT_ADDON)) { - $conf->global->MYMODULE_MYOBJECT_ADDON = 'mod_mymobject_standard'; + $conf->global->MYMODULE_MYOBJECT_ADDON = 'mod_myobject_standard'; } if (!empty($conf->global->MYMODULE_MYOBJECT_ADDON)) @@ -946,23 +948,28 @@ class MyObject extends CommonObject return ''; } - $obj = new $classname(); - $numref = $obj->getNextValue($this); + if (class_exists($classname)) { + $obj = new $classname(); + $numref = $obj->getNextValue($this); - if ($numref != "") - { - return $numref; - } - else - { - $this->error = $obj->error; - //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error); + if ($numref != '' && $numref != '-1') + { + return $numref; + } + else + { + $this->error = $obj->error; + //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error); + return ""; + } + } else { + print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname; return ""; } } else { - print $langs->trans("Error")." ".$langs->trans("Error_MYMODULE_MYOBJECT_ADDON_NotDefined"); + print $langs->trans("ErrorNumberingModuleNotSetup", $this->element); return ""; } } @@ -982,6 +989,9 @@ class MyObject extends CommonObject { global $conf, $langs; + $result = 0; + $includedocgeneration = 0; + $langs->load("mymodule@mymodule"); if (!dol_strlen($modele)) { @@ -996,7 +1006,11 @@ class MyObject extends CommonObject $modelpath = "core/modules/mymodule/doc/"; - return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams); + if ($includedocgeneration) { + $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams); + } + + return $result; } /** diff --git a/htdocs/modulebuilder/template/core/modules/mymodule/mod_myobject_advanced.php b/htdocs/modulebuilder/template/core/modules/mymodule/mod_myobject_advanced.php index 26866a6b9f1..8ae1284c918 100644 --- a/htdocs/modulebuilder/template/core/modules/mymodule/mod_myobject_advanced.php +++ b/htdocs/modulebuilder/template/core/modules/mymodule/mod_myobject_advanced.php @@ -98,15 +98,20 @@ class mod_myobject_advanced extends ModeleNumRefMyObject */ public function getExample() { - global $conf,$langs,$mysoc; + global $conf, $db, $langs, $mysoc; - $old_code_client=$mysoc->code_client; + $object = new MyObject($db); + $object->initAsSpecimen(); + + /*$old_code_client=$mysoc->code_client; $old_code_type=$mysoc->typent_code; $mysoc->code_client='CCCCCCCCCC'; - $mysoc->typent_code='TTTTTTTTTT'; - $numExample = $this->getNextValue($mysoc, ''); - $mysoc->code_client=$old_code_client; - $mysoc->typent_code=$old_code_type; + $mysoc->typent_code='TTTTTTTTTT';*/ + + $numExample = $this->getNextValue($object, ''); + + /*$mysoc->code_client=$old_code_client; + $mysoc->typent_code=$old_code_type;*/ if (! $numExample) { diff --git a/htdocs/modulebuilder/template/core/modules/mymodule/mod_myobject_standard.php b/htdocs/modulebuilder/template/core/modules/mymodule/mod_myobject_standard.php index e18e7636b6d..a213fee7174 100644 --- a/htdocs/modulebuilder/template/core/modules/mymodule/mod_myobject_standard.php +++ b/htdocs/modulebuilder/template/core/modules/mymodule/mod_myobject_standard.php @@ -76,9 +76,10 @@ class mod_myobject_standard extends ModeleNumRefMyObject * Checks if the numbers already in force in the data base do not * cause conflicts that would prevent this numbering from working. * - * @return boolean false if conflict, true if ok + * @param Object $object Object we need next value for + * @return boolean false if conflict, true if ok */ - public function canBeActivated() + public function canBeActivated($object) { global $conf,$langs,$db; @@ -88,7 +89,12 @@ class mod_myobject_standard extends ModeleNumRefMyObject $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; $sql.= " FROM ".MAIN_DB_PREFIX."mymodule_myobject"; $sql.= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; - $sql.= " AND entity = ".$conf->entity; + if ($object->ismultientitymanaged == 1) { + $sql.= " AND entity = ".$conf->entity; + } + elseif ($object->ismultientitymanaged == 2) { + // TODO + } $resql=$db->query($sql); if ($resql) @@ -121,7 +127,12 @@ class mod_myobject_standard extends ModeleNumRefMyObject $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; $sql.= " FROM ".MAIN_DB_PREFIX."mymodule_myobject"; $sql.= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; - $sql.= " AND entity = ".$conf->entity; + if ($object->ismultientitymanaged == 1) { + $sql.= " AND entity = ".$conf->entity; + } + elseif ($object->ismultientitymanaged == 2) { + // TODO + } $resql=$db->query($sql); if ($resql) diff --git a/htdocs/modulebuilder/template/myobject_card.php b/htdocs/modulebuilder/template/myobject_card.php index 93eb7560aaa..97adff0558f 100644 --- a/htdocs/modulebuilder/template/myobject_card.php +++ b/htdocs/modulebuilder/template/myobject_card.php @@ -290,7 +290,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea if ($action == 'clone') { // Create an array for form $formquestion = array(); - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneMyObject', $object->ref), 'confirm_clone', $formquestion, 'yes', 1); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneAsk', $object->ref), 'confirm_clone', $formquestion, 'yes', 1); } // Confirmation of action xxxx @@ -581,7 +581,6 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea } //Select mail models is same action as presend - /* if (GETPOST('modelselected')) $action = 'presend'; // Presend form @@ -591,7 +590,6 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $trackid = 'myobject'.$object->id; include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php'; - */ } // End of page diff --git a/htdocs/product/card.php b/htdocs/product/card.php index f4e959a9459..ad793f4f7d3 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -1272,7 +1272,13 @@ else // Accountancy_code_buy print ''.$langs->trans("ProductAccountancyBuyCode").''; print ''; - print $formaccounting->select_account(GETPOST('accountancy_code_buy', 'alpha'), 'accountancy_code_buy', 1, null, 1, 1, ''); + if($type == 0) + { + $accountancy_code_buy = (GETPOST('accountancy_code_buy', 'alpha')?(GETPOST('accountancy_code_buy', 'alpha')):$conf->global->ACCOUNTING_PRODUCT_BUY_ACCOUNT); + } else { + $accountancy_code_buy = GETPOST('accountancy_code_buy', 'alpha'); + } + print $formaccounting->select_account($accountancy_code_buy, 'accountancy_code_buy', 1, null, 1, 1, ''); print ''; } else // For external software diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index 1e189026366..0cf6b344abf 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -796,11 +796,11 @@ class Products extends DolibarrApi } if ($result) { - $this->productsupplier->fetch($id, $ref); - $this->productsupplier->list_product_fournisseur_price($id, '', '', 0, 0); + $product_fourn = new ProductFournisseur($this->db); + $product_fourn_list = $product_fourn->list_product_fournisseur_price($this->product->id, '', '', 0, 0); } - return $this->_cleanObjectDatas($this->productsupplier); + return $this->_cleanObjectDatas($product_fourn_list); } /** diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index bfdc9338b87..f8b71082b21 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -1013,12 +1013,13 @@ class Product extends CommonObject $sql .= ", accountancy_code_sell= '".$this->db->escape($this->accountancy_code_sell)."'"; $sql .= ", accountancy_code_sell_intra= '".$this->db->escape($this->accountancy_code_sell_intra)."'"; $sql .= ", accountancy_code_sell_export= '".$this->db->escape($this->accountancy_code_sell_export)."'"; - $sql .= ", desiredstock = ".((isset($this->desiredstock) && $this->desiredstock != '') ? (int) $this->desiredstock : "null"); + $sql .= ", desiredstock = ".((isset($this->desiredstock) && is_numeric($this->desiredstock)) ? (int) $this->desiredstock : "null"); $sql .= ", cost_price = ".($this->cost_price != '' ? $this->db->escape($this->cost_price) : 'null'); $sql .= ", fk_unit= ".(!$this->fk_unit ? 'NULL' : (int) $this->fk_unit); $sql .= ", price_autogen = ".(!$this->price_autogen ? 0 : 1); $sql .= ", fk_price_expression = ".($this->fk_price_expression != 0 ? (int) $this->fk_price_expression : 'NULL'); $sql .= ", fk_user_modif = ".($user->id > 0 ? $user->id : 'NULL'); + // stock field is not here because it is a denormalized value from product_stock. $sql .= " WHERE rowid = ".$id; diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index 7b92af43ef0..e0266172463 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -109,7 +109,7 @@ class MouvementStock extends CommonObject * @param string $batch batch number * @param boolean $skip_batch If set to true, stock movement is done without impacting batch record * @param int $id_product_batch Id product_batch (when skip_batch is false and we already know which record of product_batch to use) - * @return int <0 if KO, 0 if fk_product is null, >0 if OK + * @return int <0 if KO, 0 if fk_product is null or product id does not exists, >0 if OK */ public function _create($user, $fk_product, $entrepot_id, $qty, $type, $price = 0, $label = '', $inventorycode = '', $datem = '', $eatby = '', $sellby = '', $batch = '', $skip_batch = false, $id_product_batch = 0) { @@ -155,13 +155,15 @@ class MouvementStock extends CommonObject $product = new Product($this->db); $result=$product->fetch($fk_product); - if ($result < 0) - { + if ($result < 0) { $this->error = $product->error; $this->errors = $product->errors; dol_print_error('', "Failed to fetch product"); return -1; } + if ($product->id <= 0) { // Can happen if database is corrupted + return 0; + } $this->db->begin(); diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index 2ad465bdedb..ae5c936ef1e 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -702,7 +702,10 @@ while ($i < ($limit ? min($num, $limit) : $num)) //depending on conf, use either physical stock or //virtual stock to compute the stock to buy value - $stocktobuy = max(max($desiredstock, $alertstock) - $stock - $ordered, 0); + + if(empty($usevirtualstock)) $stocktobuy = max(max($desiredstock, $alertstock) - $stock - $ordered, 0); + else $stocktobuy = max(max($desiredstock, $alertstock) - $stock, 0); //ordered is already in $stock in virtual mode + $disabled = ''; if ($ordered > 0) { diff --git a/htdocs/supplier_proposal/class/supplier_proposal.class.php b/htdocs/supplier_proposal/class/supplier_proposal.class.php index 6f41426ee80..3c2d68f653d 100644 --- a/htdocs/supplier_proposal/class/supplier_proposal.class.php +++ b/htdocs/supplier_proposal/class/supplier_proposal.class.php @@ -1800,25 +1800,25 @@ class SupplierProposal extends CommonObject */ public function updateOrCreatePriceFournisseur($user) { - $productsupplier = new ProductFournisseur($this->db); + global $conf; dol_syslog(get_class($this)."::updateOrCreatePriceFournisseur", LOG_DEBUG); foreach ($this->lines as $product) { if ($product->subprice <= 0) continue; + $productsupplier = new ProductFournisseur($this->db); - $idProductFourn = $productsupplier->find_min_price_product_fournisseur($product->fk_product, $product->qty); - $res = $productsupplier->fetch($idProductFourn); + $multicurrency_tx = 1; + $fk_multicurrency = 0; - if ($productsupplier->id) { - if ($productsupplier->fourn_qty == $product->qty) { - $this->updatePriceFournisseur($productsupplier->product_fourn_price_id, $product, $user); - } else { - $this->createPriceFournisseur($product, $user); - } - } else { - $this->createPriceFournisseur($product, $user); - } + if(empty($this->thirdparty)) $this->fetch_thirdparty(); + + $ref_fourn = $product->ref_fourn; + if(empty($ref_fourn)) $ref_fourn = $product->ref_supplier; + if(!empty($conf->multicurrency->enabled) && !empty($product->multicurrency_code)) list($fk_multicurrency, $multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $product->multicurrency_code); + $productsupplier->id = $product->fk_product; + + $productsupplier->update_buyprice($product->qty, $product->subprice, $user, 'HT', $this->thirdparty, '', $ref_fourn, $product->tva_tx, 0, 0, 0, $product->info_bits, '', '', array(), '', $product->multicurrency_subprice, 'HT', $multicurrency_tx, $product->multicurrency_code, '', '', ''); } return 1; @@ -1856,11 +1856,12 @@ class SupplierProposal extends CommonObject */ public function createPriceFournisseur($product, $user) { - $price=price2num($product->subprice*$product->qty, 'MU'); + global $conf; + + $price=price2num($product->subprice*$product->qty, 'MU'); $qty=price2num($product->qty); $unitPrice = price2num($product->subprice, 'MU'); $now=dol_now(); - $values = array( "'".$this->db->idate($now)."'", $product->fk_product, @@ -1872,9 +1873,28 @@ class SupplierProposal extends CommonObject $product->tva_tx, $user->id ); + if (!empty($conf->multicurrency->enabled)) { + if (!empty($product->multicurrency_code)) { + include_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php'; + $multicurrency = new MultiCurrency($this->db); //need to fetch because empty fk_multicurrency and rate + $multicurrency->fetch(0, $product->multicurrency_code); + if(! empty($multicurrency->id)) { + $values[] = $multicurrency->id; + $values[] = "'".$product->multicurrency_code."'"; + $values[] = $product->multicurrency_subprice; + $values[] = $product->multicurrency_total_ht; + $values[] = $multicurrency->rate->rate; + } + else { + for($i = 0; $i < 5; $i++) $values[] = 'NULL'; + } + } + } $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'product_fournisseur_price '; - $sql .= '(datec, fk_product, fk_soc, ref_fourn, price, quantity, unitprice, tva_tx, fk_user) VALUES ('.implode(',', $values).')'; + $sql .= '(datec, fk_product, fk_soc, ref_fourn, price, quantity, unitprice, tva_tx, fk_user'; + if(!empty($conf->multicurrency->enabled) && !empty($product->multicurrency_code)) $sql .= ',fk_multicurrency, multicurrency_code, multicurrency_unitprice, multicurrency_price, multicurrency_tx'; + $sql .= ') VALUES ('.implode(',', $values).')'; $resql = $this->db->query($sql); if (!$resql) { diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index e800689b15d..189e5a56cec 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -47,7 +47,7 @@ if (defined('THEME_ONLY_CONSTANT')) return; session_cache_limiter('public'); -require_once '../../main.inc.php'; +require_once __DIR__.'/../../main.inc.php'; // __DIR__ allow this script to be included in custom themes require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; // Load user to have $user->conf loaded (not done into main because of NOLOGIN constant defined) diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index 8ca8bd22bfe..d59581fa914 100644 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -637,7 +637,7 @@ if ($action == 'create' || $action == 'presend') $defaultref = ''; } - $formticket->showForm(1); + $formticket->showForm(1, 'create'); } if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'dellink' || $action == 'presend' || $action == 'presend_addmessage' || $action == 'close' || $action == 'delete' || $action == 'editcustomer' || $action == 'progression' || $action == 'reopen' diff --git a/htdocs/user/card.php b/htdocs/user/card.php index d12f6064131..152103cc5db 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -1243,13 +1243,8 @@ if ($action == 'create' || $action == 'adduserldap') } // Other attributes - $parameters = array('objectsrc' => $objectsrc, 'colspan' => ' colspan="3"'); - $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook - print $hookmanager->resPrint; - if (empty($reshook)) - { - print $object->showOptionals($extrafields, 'edit'); - } + $parameters = array('colspan' => ' colspan="3"'); + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php'; // Note print ''; @@ -2515,74 +2510,6 @@ else } } - // // Skype - // if (! empty($conf->socialnetworks->enabled)) - // { - // print ''.$langs->trans("Skype").''; - // print ''; - // if ($caneditfield && empty($object->ldap_sid)) - // { - // print ''; - // } - // else - // { - // print ''; - // print $object->skype; - // } - // print ''; - // } - - // // Twitter - // if (! empty($conf->socialnetworks->enabled)) - // { - // print ''.$langs->trans("Twitter").''; - // print ''; - // if ($caneditfield && empty($object->ldap_sid)) - // { - // print ''; - // } - // else - // { - // print ''; - // print $object->twitter; - // } - // print ''; - // } - - // // Facebook - // if (! empty($conf->socialnetworks->enabled)) - // { - // print ''.$langs->trans("Facebook").''; - // print ''; - // if ($caneditfield && empty($object->ldap_sid)) - // { - // print ''; - // } - // else - // { - // print ''; - // print $object->facebook; - // } - // print ''; - // } - - // // LinkedIn - // if (! empty($conf->socialnetworks->enabled)) - // { - // print ''.$langs->trans("LinkedIn").''; - // print ''; - // if ($caneditfield && empty($object->ldap_sid)) - // { - // print ''; - // } - // else - // { - // print ''; - // print $object->linkedin; - // } - // print ''; - // } - // OpenID url if (isset($conf->file->main_authentication) && preg_match('/openid/', $conf->file->main_authentication) && !empty($conf->global->MAIN_OPENIDURL_PERUSER)) { @@ -2738,12 +2665,12 @@ else // Other attributes $parameters = array('colspan' => ' colspan="2"'); + //include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_edit.tpl.php'; // We do not use common tpl here because we need a special test on $caneditfield $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; if (empty($reshook)) { - if ($caneditfield) - { + if ($caneditfield) { print $object->showOptionals($extrafields, 'edit'); } else { print $object->showOptionals($extrafields, 'view'); diff --git a/scripts/user/migrate_picture_path.php b/scripts/user/migrate_picture_path.php new file mode 100755 index 00000000000..b0ca99dd977 --- /dev/null +++ b/scripts/user/migrate_picture_path.php @@ -0,0 +1,129 @@ +#!/usr/bin/env php + + * Copyright (C) 2015 Jean Heimburger + * + * 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 scripts/product/migrate_picture_path.php + * \ingroup scripts + * \brief Migrate pictures from old system prior to 3.7 to new path for 3.7+ + */ +$sapi_type = php_sapi_name(); +$script_file = basename(__FILE__); +$path = __DIR__ . '/'; + +// Test if batch mode +if (substr($sapi_type, 0, 3) == 'cgi') { + echo "Error: You are using PHP for CGI. To execute " . $script_file . " from command line, you must use PHP for CLI mode.\n"; + exit(- 1); +} + +@set_time_limit(0); // No timeout for this script +define('EVEN_IF_ONLY_LOGIN_ALLOWED', 1); // Set this define to 0 if you want to lock your script when dolibarr setup is "locked to admin user only". + +// Include and load Dolibarr environment variables +require_once $path . "../../htdocs/master.inc.php"; +require_once DOL_DOCUMENT_ROOT . "/user/class/user.class.php"; +require_once DOL_DOCUMENT_ROOT . "/core/lib/files.lib.php"; +// After this $db, $mysoc, $langs, $conf and $hookmanager are defined (Opened $db handler to database will be closed at end of file). +// $user is created but empty. + +// $langs->setDefaultLang('en_US'); // To change default language of $langs +$langs->load("main"); // To load language file for default language + +// Global variables +$version = DOL_VERSION; +$error = 0; +$forcecommit = 0; + +print "***** " . $script_file . " (" . $version . ") pid=" . dol_getmypid() . " *****\n"; +dol_syslog($script_file . " launched with arg " . join(',', $argv)); + +if (! isset($argv[1]) || $argv[1] != 'user') { + print "Usage: $script_file user\n"; + exit(- 1); +} + +print '--- start' . "\n"; + +// Case to migrate products path +if ($argv[1] == 'user') { + $u = new User($db); + + $sql = "SELECT rowid as uid from " . MAIN_DB_PREFIX . "user"; // Get list of all products + $resql = $db->query($sql); + if ($resql) { + while ($obj = $db->fetch_object($resql)) { + $u->fetch($obj->uid); + print " migrating user id=" . $u->id . " ref=" . $u->ref . "\n"; + migrate_user_filespath($u); + } + } else { + print "\n sql error " . $sql; + exit(); + } +} + +$db->close(); // Close $db database opened handler + +exit($error); + + +/** + * Migrate file from old path to new one for user $u + * + * @param User $u Object user + * @return void + */ +function migrate_user_filespath($u) +{ + global $conf; + + // Les fichiers joints des users sont toujours sur l'entité 1 + $dir = $conf->user->dir_output; + $origin = $dir . '/' . get_exdir($u->id, 2, 0, 0, $u, 'user'); + $destin = $dir . '/' . $u->id; + + $error = 0; + + $origin_osencoded = dol_osencode($origin); + $destin_osencoded = dol_osencode($destin); + dol_mkdir($destin); + + if (dol_is_dir($origin)) { + $handle = opendir($origin_osencoded); + if (is_resource($handle)) { + while (($file = readdir($handle)) !== false) { + if ($file != '.' && $file != '..' && is_dir($origin_osencoded . '/' . $file)) { + $thumbs = opendir($origin_osencoded . '/' . $file); + if (is_resource($thumbs)) { + dol_mkdir($destin . '/' . $file); + while (($thumb = readdir($thumbs)) !== false) { + dol_move($origin . '/' . $file . '/' . $thumb, $destin . '/' . $file . '/' . $thumb); + } + // dol_delete_dir($origin.'/'.$file); + } + } else { + if (dol_is_file($origin . '/' . $file)) { + dol_move($origin . '/' . $file, $destin . '/' . $file); + } + } + } + } + } +}