diff --git a/ChangeLog b/ChangeLog index 7089658872e..a8c32a72670 100644 --- a/ChangeLog +++ b/ChangeLog @@ -405,6 +405,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 aa487ad4174..cbbf434709b 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/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index b2d1c09bd25..a4b4cdbfd11 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -4420,7 +4420,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/facture/class/facture-rec.class.php b/htdocs/compta/facture/class/facture-rec.class.php index 524d553effd..e07f631efd4 100644 --- a/htdocs/compta/facture/class/facture-rec.class.php +++ b/htdocs/compta/facture/class/facture-rec.class.php @@ -325,6 +325,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 9be5607b62d..1f450289506 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/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/fourn/class/fournisseur.product.class.php b/htdocs/fourn/class/fournisseur.product.class.php index 07059830e6a..bbd82970121 100644 --- a/htdocs/fourn/class/fournisseur.product.class.php +++ b/htdocs/fourn/class/fournisseur.product.class.php @@ -435,7 +435,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)."'"); @@ -455,7 +455,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/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/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index 3903e374713..b7c92215e2a 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -133,7 +133,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) { @@ -178,14 +178,17 @@ class MouvementStock extends CommonObject $mvid = 0; $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/supplier_proposal/class/supplier_proposal.class.php b/htdocs/supplier_proposal/class/supplier_proposal.class.php index ab451b02177..adbe97456fa 100644 --- a/htdocs/supplier_proposal/class/supplier_proposal.class.php +++ b/htdocs/supplier_proposal/class/supplier_proposal.class.php @@ -1806,25 +1806,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; @@ -1862,9 +1862,12 @@ class SupplierProposal extends CommonObject */ public function createPriceFournisseur($product, $user) { + global $conf; + $price = price2num($product->subprice * $product->qty, 'MU'); $qty = price2num($product->qty); $unitPrice = price2num($product->subprice, 'MU'); + $now = dol_now(); $values = array( @@ -1878,9 +1881,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 7b3216e9cf5..8f2a9f4eb2c 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)