Merge branch '11.0' of git@github.com:Dolibarr/dolibarr.git into develop

Conflicts:
	htdocs/product/stock/class/mouvementstock.class.php
	htdocs/supplier_proposal/class/supplier_proposal.class.php
This commit is contained in:
Laurent Destailleur 2020-04-02 16:51:50 +02:00
commit 99ddd25ad5
13 changed files with 173 additions and 39 deletions

View File

@ -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

View File

@ -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);

View File

@ -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();

View File

@ -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

View File

@ -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 '<tr class="oddeven">';
// Month
print "<td>".dol_print_date(dol_mktime(12, 0, 0, $mois_modulo, 1, 2000), "%B")."</td>";
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;

View File

@ -53,16 +53,17 @@ function report_header($reportname, $notused, $period, $periodlink, $description
$head[$h][1] = $langs->trans("Report");
$head[$h][2] = 'report';
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].$varlink.'">';
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].$varlink.'">'."\n";
print '<input type="hidden" name="token" value="'.newToken().'">'."\n";
dol_fiche_head($head, 'report');
foreach($moreparam as $key => $value)
{
print '<input type="hidden" name="'.$key.'" value="'.$value.'">';
print '<input type="hidden" name="'.$key.'" value="'.$value.'">'."\n";
}
print '<table class="border tableforfield centpercent">';
print '<table class="border tableforfield centpercent">'."\n";
$variante = ($periodlink || $exportlink);
@ -73,7 +74,7 @@ function report_header($reportname, $notused, $period, $periodlink, $description
print $reportname;
print '</td>';
if ($variante) print '<td></td>';
print '</tr>';
print '</tr>'."\n";
// Calculation mode
if ($calcmode)
@ -84,7 +85,7 @@ function report_header($reportname, $notused, $period, $periodlink, $description
print $calcmode;
if ($variante) print '<td></td>';
print '</td>';
print '</tr>';
print '</tr>'."\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 '<td class="nowraponall">'.$periodlink.'</td>';
print '</td>';
print '</tr>';
print '</tr>'."\n";
// Ligne de description
print '<tr>';
print '<td>'.$langs->trans("ReportDescription").'</td>';
print '<td>'.$description.'</td>';
if ($variante) print '<td></td>';
print '</tr>';
print '</tr>'."\n";
// Ligne d'export
print '<tr>';
@ -110,9 +111,9 @@ function report_header($reportname, $notused, $period, $periodlink, $description
print dol_print_date($builddate, 'dayhour');
print '</td>';
if ($variante) print '<td>'.($exportlink ? $langs->trans("Export").': '.$exportlink : '').'</td>';
print '</tr>';
print '</tr>'."\n";
print '</table>';
print '</table>'."\n";
dol_fiche_end();

View File

@ -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);

View File

@ -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++;
}

View File

@ -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;

View File

@ -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),

View File

@ -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();

View File

@ -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) {

View File

@ -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)