diff --git a/htdocs/comm/multiprix.php b/htdocs/comm/multiprix.php index c4e0df11df2..6d80626242d 100644 --- a/htdocs/comm/multiprix.php +++ b/htdocs/comm/multiprix.php @@ -20,7 +20,7 @@ /** * \file htdocs/comm/multiprix.php * \ingroup societe - * \brief Onglet choix du niveau de prix + * \brief Tab to set the price level of a thirdparty */ require '../main.inc.php'; @@ -64,20 +64,11 @@ $userstatic = new User($db); if ($_socid > 0) { - // On recupere les donnees societes par l'objet + // We load data of thirdparty $objsoc = new Societe($db); $objsoc->id = $_socid; $objsoc->fetch($_socid, $to); - if ($errmesg) - { - print '
'.$errmesg.'

'; - } - - - /* - * Affichage onglets - */ $head = societe_prepare_head($objsoc); @@ -91,7 +82,7 @@ if ($_socid > 0) dol_fiche_head($head, $tabchoice, $langs->trans("ThirdParty"), 0, 'company'); - print ''; + print '
'; print '"; diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index ffed0ec77b0..bc51fabfefc 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -3968,7 +3968,7 @@ elseif ($id > 0 || !empty($ref)) if ($result > 0) { print '. '.$langs->trans( "GeneratedFromTemplate", - ''.$tmptemplate->ref.'' + ''.$tmptemplate->ref.'' ).''; } } diff --git a/htdocs/compta/sociales/card.php b/htdocs/compta/sociales/card.php index f8a9a2d2975..ff2cb84dbce 100644 --- a/htdocs/compta/sociales/card.php +++ b/htdocs/compta/sociales/card.php @@ -604,7 +604,7 @@ if ($id > 0) */ $sql = "SELECT p.rowid, p.num_paiement, datep as dp, p.amount,"; $sql .= " c.code as type_code,c.libelle as paiement_type,"; - $sql .= ' ba.rowid as baid, ba.ref as baref, ba.label, ba.number as banumber, ba.account_number, ba.fk_accountancy_journal'; + $sql .= ' ba.rowid as baid, ba.ref as baref, ba.label, ba.number as banumber, ba.account_number, ba.currency_code as bacurrency_code, ba.fk_accountancy_journal'; $sql .= " FROM ".MAIN_DB_PREFIX."paiementcharge as p"; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'bank as b ON p.fk_bank = b.rowid'; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'bank_account as ba ON b.fk_account = ba.rowid'; @@ -653,6 +653,7 @@ if ($id > 0) $bankaccountstatic->ref = $objp->baref; $bankaccountstatic->label = $objp->baref; $bankaccountstatic->number = $objp->banumber; + $bankaccountstatic->currency_code = $objp->bacurrency_code; if (!empty($conf->accounting->enabled)) { $bankaccountstatic->account_number = $objp->account_number; diff --git a/htdocs/core/actions_setnotes.inc.php b/htdocs/core/actions_setnotes.inc.php index b9473de1b31..425204e00a4 100644 --- a/htdocs/core/actions_setnotes.inc.php +++ b/htdocs/core/actions_setnotes.inc.php @@ -33,7 +33,7 @@ if ($action == 'setnote_public' && ! empty($permissionnote) && ! GETPOST('cancel if (empty($action) || ! is_object($object) || empty($id)) dol_print_error('', 'Include of actions_setnotes.inc.php was done but required variable was not set before'); if (empty($object->id)) $object->fetch($id); // Fetch may not be already done - $result_update=$object->update_note(dol_html_entity_decode(GETPOST('note_public', 'none'), ENT_QUOTES), '_public'); + $result_update = $object->update_note(dol_html_entity_decode(GETPOST('note_public', 'none'), ENT_QUOTES, 'UTF-8', 1), '_public'); if ($result_update < 0) setEventMessages($object->error, $object->errors, 'errors'); elseif (in_array($object->table_element, array('supplier_proposal', 'propal', 'commande_fournisseur', 'commande', 'facture_fourn', 'facture'))) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 2c2064a0619..a9308ae03fb 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -213,7 +213,7 @@ class Form $valuetoshow = price2num($editvalue ? $editvalue : $value); $ret .= ''; } - elseif (preg_match('/^text/', $typeofdata) || preg_match('/^note/', $typeofdata)) + elseif (preg_match('/^text/', $typeofdata) || preg_match('/^note/', $typeofdata)) // if wysiwyg is enabled $typeofdata = 'ckeditor' { $tmp = explode(':', $typeofdata); $cols = $tmp[2]; @@ -225,8 +225,10 @@ class Form } $valuetoshow = ($editvalue ? $editvalue : $value); - $ret .= ''; } diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index ba47a1bcb76..8805da44a96 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -5701,14 +5701,19 @@ function dol_htmlcleanlastbr($stringtodecode) /** * Replace html_entity_decode functions to manage errors * - * @param string $a Operand a - * @param string $b Operand b (ENT_QUOTES=convert simple and double quotes) - * @param string $c Operand c - * @return string String decoded + * @param string $a Operand a + * @param string $b Operand b (ENT_QUOTES=convert simple and double quotes) + * @param string $c Operand c + * @param string $keepsomeentities Entities but &, <, >, " are not converted. + * @return string String decoded */ -function dol_html_entity_decode($a, $b, $c = 'UTF-8') +function dol_html_entity_decode($a, $b, $c = 'UTF-8', $keepsomeentities = 0) { - return html_entity_decode($a, $b, $c); + $newstring = $a; + if ($keepsomeentities) $newstring = strtr($newstring, array('&'=>'__andamp__', '<'=>'__andlt__', '>'=>'__andgt__', '"'=>'__dquot__')); + $newstring = html_entity_decode($newstring, $b, $c); + if ($keepsomeentities) $newstring = strtr($newstring, array('__andamp__'=>'&', '__andlt__'=>'<', '__andgt__'=>'>', '__dquot__'=>'"')); + return $newstring; } /** diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index 374e740ea40..9056f3bde9d 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -620,7 +620,7 @@ if (!empty($usemargins) && $user->rights->margins->creer) /* When changing predefined product, we reload list of supplier prices required for margin combo */ $("#idprod, #idprodfournprice").change(function() { - console.log("#idprod, #idprodfournprice change triggered this.val = "+$(this).val()); + console.log("Call method change() after change on #idprod or #idprodfournprice. this.val = "+$(this).val()); setforpredef(); // TODO Keep vat combo visible and set it to first entry into list that match result of get_default_tva @@ -631,6 +631,7 @@ if (!empty($usemargins) && $user->rights->margins->creer) { ?> // Get the HT price for the product and display it + console.log("Load price without tax and set it into #price_ht"); $.post('/product/ajax/products.php?action=fetch', { 'id': $(this).val(), 'socid' : socid; ?> }, function(data) { jQuery("#price_ht").val(data.price_ht); }, diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index b8745aa0d2b..e03b050d693 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -705,7 +705,7 @@ class CommandeFournisseur extends CommonOrder */ public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $save_lastsearch_value = -1, $addlinktonotes = 0) { - global $langs, $conf; + global $langs, $conf, $user; $result = ''; $label = ''.$langs->trans("ShowOrder").''; diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index 1f00720a12d..587f9fbb226 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -2253,7 +2253,7 @@ class FactureFournisseur extends CommonInvoice */ public function getNomUrl($withpicto = 0, $option = '', $max = 0, $short = 0, $moretitle = '', $notooltip = 0, $save_lastsearch_value = -1, $addlinktonotes = 0) { - global $langs, $conf; + global $langs, $conf, $user; $result = ''; diff --git a/htdocs/install/doctemplates/websites/website_template-corporate.zip b/htdocs/install/doctemplates/websites/website_template-corporate.zip index a9773ce496b..f83fecc2c2e 100644 Binary files a/htdocs/install/doctemplates/websites/website_template-corporate.zip and b/htdocs/install/doctemplates/websites/website_template-corporate.zip differ diff --git a/htdocs/install/doctemplates/websites/website_template-stellar.zip b/htdocs/install/doctemplates/websites/website_template-stellar.zip index 59ebb470d72..ca73b125015 100644 Binary files a/htdocs/install/doctemplates/websites/website_template-stellar.zip and b/htdocs/install/doctemplates/websites/website_template-stellar.zip differ diff --git a/htdocs/langs/en_US/other.lang b/htdocs/langs/en_US/other.lang index 7ee672f089b..052b1b25859 100644 --- a/htdocs/langs/en_US/other.lang +++ b/htdocs/langs/en_US/other.lang @@ -267,7 +267,7 @@ WEBSITE_PAGEURL=URL of page WEBSITE_TITLE=Title WEBSITE_DESCRIPTION=Description WEBSITE_IMAGE=Image -WEBSITE_IMAGEDesc=Relative path of the image media. You can keep this empty as this is rarely used (it can be used by dynamic content to show a preview of a list of blog posts). +WEBSITE_IMAGEDesc=Relative path of the image media. You can keep this empty as this is rarely used (it can be used by dynamic content to show a thumbnail in a list of blog posts). Use __WEBSITEKEY__ in the path if path depends on website name. WEBSITE_KEYWORDS=Keywords LinesToImport=Lines to import diff --git a/htdocs/product/ajax/products.php b/htdocs/product/ajax/products.php index 19fd7926453..918950179c7 100644 --- a/htdocs/product/ajax/products.php +++ b/htdocs/product/ajax/products.php @@ -59,8 +59,9 @@ dol_syslog(join(',', $_GET)); if (!empty($action) && $action == 'fetch' && !empty($id)) { - // When action='fetch', id must be the product id. + // action='fetch' is used to get product information on a product. So when action='fetch', id must be the product id. require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; + require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; $outjson = array(); @@ -77,6 +78,13 @@ if (!empty($action) && $action == 'fetch' && !empty($id)) $found = false; + $price_level = 1; + if ($socid > 0 && !empty($conf->global->PRODUIT_MULTIPRICES)) { + $thirdpartytemp = new Societe($db); + $thirdpartytemp->fetch($socid); + $price_level = $thirdpartytemp->price_level; + } + // Price by qty if (!empty($price_by_qty_rowid) && $price_by_qty_rowid >= 1 && (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY))) // If we need a particular price related to qty { @@ -100,14 +108,13 @@ if (!empty($action) && $action == 'fetch' && !empty($id)) } // Multiprice - if (!$found && isset($price_level) && $price_level >= 1 && (!empty($conf->global->PRODUIT_MULTIPRICES))) // If we need a particular price - // level (from 1 to 6) + if (!$found && isset($price_level) && $price_level >= 1 && (!empty($conf->global->PRODUIT_MULTIPRICES))) // If we need a particular price level (from 1 to 6) { $sql = "SELECT price, price_ttc, price_base_type, tva_tx"; $sql .= " FROM ".MAIN_DB_PREFIX."product_price "; - $sql .= " WHERE fk_product='".$id."'"; + $sql .= " WHERE fk_product = '".$id."'"; $sql .= " AND entity IN (".getEntity('productprice').")"; - $sql .= " AND price_level=".$price_level; + $sql .= " AND price_level = ".((int) $price_level); $sql .= " ORDER BY date_price"; $sql .= " DESC LIMIT 1"; @@ -160,8 +167,7 @@ else { require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; - $langs->load("products"); - $langs->load("main"); + $langs->loadLangs(array("main", "products")); top_httphead(); @@ -186,6 +192,7 @@ else $searchkey = (($idprod && GETPOST($idprod, 'alpha')) ? GETPOST($idprod, 'alpha') : (GETPOST($htmlname, 'alpha') ? GETPOST($htmlname, 'alpha') : '')); $form = new Form($db); + if (empty($mode) || $mode == 1) { // mode=1: customer $arrayresult = $form->select_produits_list("", $htmlname, $type, 0, $price_level, $searchkey, $status, $finished, $outjson, $socid, '1', 0, '', $hidepriceinlabel, $warehouseStatus); } elseif ($mode == 2) { // mode=2: supplier diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index 708ff1c6464..1e189026366 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -1596,11 +1596,19 @@ class Products extends DolibarrApi } if ($includestockdata) { - $this->product->load_stock(); + $this->product->load_stock(); + + if (is_array($this->product->stock_warehouse)) { + foreach($this->product->stock_warehouse as $keytmp => $valtmp) { + if (is_array($this->product->stock_warehouse[$keytmp]->detail_batch)) { + foreach($this->product->stock_warehouse[$keytmp]->detail_batch as $keytmp2 => $valtmp2) { + unset($this->product->stock_warehouse[$keytmp]->detail_batch[$keytmp2]->db); + } + } + } + } } - - if ($includesubproducts) { $childsArbo = $this->product->getChildsArbo($id, 1); diff --git a/htdocs/product/stock/class/api_stockmovements.class.php b/htdocs/product/stock/class/api_stockmovements.class.php index cfa901bce30..9951c05d323 100644 --- a/htdocs/product/stock/class/api_stockmovements.class.php +++ b/htdocs/product/stock/class/api_stockmovements.class.php @@ -154,51 +154,42 @@ class StockMovements extends DolibarrApi return $obj_ret; } - /* - * @param int $product_id Id product id {@min 1} - * @param int $warehouse_id Id warehouse {@min 1} - * @param float $qty Qty to add (Use negative value for a stock decrease) {@min 0} {@message qty must be higher than 0} - * @param string $lot Lot - * @param string $movementcode Movement code {@example INV123} - * @param string $movementlabel Movement label {@example Inventory number 123} - * @param string $price To update AWP (Average Weighted Price) when you make a stock increase (qty must be higher then 0). - */ - - /** * Create stock movement object. * You can use the following message to test this RES API: * { "product_id": 1, "warehouse_id": 1, "qty": 1, "lot": "", "movementcode": "INV123", "movementlabel": "Inventory 123", "price": 0 } + * $price Can be set to update AWP (Average Weighted Price) when you make a stock increase + * $dlc Eat-by date. Will be used if lot does not exists yet and will be created. + * $dluo Sell-by date. Will be used if lot does not exists yet and will be created. + * + * @param int $product_id Id product id {@min 1} {@from body} {@required true} + * @param int $warehouse_id Id warehouse {@min 1} {@from body} {@required true} + * @param float $qty Qty to add (Use negative value for a stock decrease) {@min 0} {@message qty must be higher than 0} {@from body} {@required true} + * @param string $lot Lot {@from body} + * @param string $movementcode Movement code {@example INV123} {@from body} + * @param string $movementlabel Movement label {@example Inventory number 123} {@from body} + * @param string $price To update AWP (Average Weighted Price) when you make a stock increase (qty must be higher then 0). {@from body} + * @param string $dlc Eat-by date. {@from body} {@type date} + * @param string $dluo Sell-by date. {@from body} {@type date} * - * @param array $request_data Request data * @return int ID of stock movement + * @throws RestException */ - //function post($product_id, $warehouse_id, $qty, $lot='', $movementcode='', $movementlabel='', $price=0) - public function post($request_data = null) + public function post($product_id, $warehouse_id, $qty, $lot = '', $movementcode = '', $movementlabel = '', $price = '', $dlc = '', $dluo = '') { if(! DolibarrApiAccess::$user->rights->stock->creer) { throw new RestException(401); } - // Check mandatory fields - //$result = $this->_validate($request_data); - - foreach($request_data as $field => $value) { - //$this->stockmovement->$field = $value; - if ($field == 'product_id') $product_id = $value; - if ($field == 'warehouse_id') $warehouse_id = $value; - if ($field == 'qty') $qty = $value; - if ($field == 'lot') $lot = $value; - if ($field == 'movementcode') $movementcode = $value; - if ($field == 'movementlabel') $movementlabel = $value; - if ($field == 'price') $price = $value; + if ($qty == 0) { + throw new RestException(503, "Making a stock movement with a quentity of 0 is not possible"); } // Type increase or decrease if ($qty >= 0) $type = 3; else $type = 2; - if($this->stockmovement->_create(DolibarrApiAccess::$user, $product_id, $warehouse_id, $qty, $type, $price, $movementlabel, $movementcode, '', '', '', $lot) <= 0) { + if($this->stockmovement->_create(DolibarrApiAccess::$user, $product_id, $warehouse_id, $qty, $type, $price, $movementlabel, $movementcode, '', $dlc, $dluo, $lot) <= 0) { throw new RestException(503, 'Error when create stock movement : '.$this->stockmovement->error); } @@ -342,7 +333,7 @@ class StockMovements extends DolibarrApi private function _validate($data) { $stockmovement = array(); - foreach (Warehouses::$FIELDS as $field) { + foreach (self::$FIELDS as $field) { if (!isset($data[$field])) throw new RestException(400, "$field field missing"); $stockmovement[$field] = $data[$field]; diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index 41d002eece8..bc4dd12e9d4 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -158,6 +158,8 @@ class MouvementStock extends CommonObject $result = $product->fetch($fk_product); if ($result < 0) { + $this->error = $product->error; + $this->errors = $product->errors; dol_print_error('', "Failed to fetch product"); return -1; } @@ -399,7 +401,8 @@ class MouvementStock extends CommonObject } else { - $this->errors[] = $this->db->lasterror(); + $this->error = $this->db->lasterror(); + $this->errors[] = $this->error; $error = -1; } diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index a832188918c..514d87d9200 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -5,7 +5,7 @@ * Copyright (C) 2005 Eric Seigne * Copyright (C) 2005-2017 Regis Houssin * Copyright (C) 2008 Patrick Raguin - * Copyright (C) 2010-2016 Juanjo Menent + * Copyright (C) 2010-2020 Juanjo Menent * Copyright (C) 2011-2013 Alexandre Spangaro * Copyright (C) 2015 Jean-François Ferry * Copyright (C) 2015 Marcos García @@ -1070,13 +1070,13 @@ else $linkback = ""; print load_fiche_titre($langs->trans("NewThirdParty"), $linkback, 'building'); - if (!empty($conf->use_javascript_ajax) && !empty($conf->global->THIRDPARTY_SUGGEST_ALSO_ADDRESS_CREATION)) - { - print "\n".''."\n"; + print '' . "\n"; - print '
'; - print '
'; - print $langs->trans("ThirdPartyType").':     '; - print '
'; - print ''; - print '     '; - print ''; - print '
'; - print "
\n"; - } + print '
'; + print '
'; + print $langs->trans("ThirdPartyType") . ':     '; + print '
'; + print ''; + print '     '; + print ''; + print '
'; + print "
\n"; + } else { + print '' . "\n"; + } + } dol_htmloutput_mesg(is_numeric($error) ? '' : $error, $errors, 'error');
'; print $langs->trans("PriceLevel").''.$objsoc->price_level."