/** * Load a product in memory from database * * @param int $id Id of product/service to load * @param string $ref Ref of product/service to load * @param string $ref_ext Ref ext of product/service to load * @param int $ignore_expression Ignores the math expression for calculating price and uses the db value instead * @return int <0 if KO, 0 if not found, >0 if OK */ function fetch($id = '', $ref = '', $ref_ext = '', $ignore_expression = 0) { include_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php'; global $langs, $conf; dol_syslog(get_class($this) . "::fetch id=" . $id . " ref=" . $ref . " ref_ext=" . $ref_ext); // Check parameters if (!$id && !$ref && !$ref_ext) { $this->error = 'ErrorWrongParameters'; dol_print_error(get_class($this) . "::fetch " . $this->error); return -1; } $sql = "SELECT rowid, ref, ref_ext, label, description, url, note, customcode, fk_country, price, price_ttc,"; $sql .= " price_min, price_min_ttc, price_base_type, tva_tx, recuperableonly as tva_npr, localtax1_tx, localtax2_tx, tosell,"; $sql .= " tobuy, fk_product_type, duration, seuil_stock_alerte, canvas,"; $sql .= " weight, weight_units, length, length_units, surface, surface_units, volume, volume_units, barcode, fk_barcode_type, finished,"; $sql .= " accountancy_code_buy, accountancy_code_sell, stock, pmp,"; $sql .= " datec, tms, import_key, entity, desiredstock, tobatch, fk_unit"; $sql .= " , fk_price_expression"; $sql .= " FROM " . MAIN_DB_PREFIX . "product"; if ($id) { $sql .= " WHERE rowid = " . $this->db->escape($id); } else { $sql .= " WHERE entity IN (" . getEntity($this->element, 1) . ")"; if ($ref) { $sql .= " AND ref = '" . $this->db->escape($ref) . "'"; } else { if ($ref_ext) { $sql .= " AND ref_ext = '" . $this->db->escape($ref_ext) . "'"; } } } $resql = $this->db->query($sql); if ($resql) { if ($this->db->num_rows($resql) > 0) { $obj = $this->db->fetch_object($resql); $this->id = $obj->rowid; $this->ref = $obj->ref; $this->ref_ext = $obj->ref_ext; $this->label = $obj->label; $this->description = $obj->description; $this->url = $obj->url; $this->note = $obj->note; $this->type = $obj->fk_product_type; $this->status = $obj->tosell; $this->status_buy = $obj->tobuy; $this->status_batch = $obj->tobatch; $this->customcode = $obj->customcode; $this->country_id = $obj->fk_country; $this->country_code = getCountry($this->country_id, 2, $this->db); $this->price = $obj->price; $this->price_ttc = $obj->price_ttc; $this->price_min = $obj->price_min; $this->price_min_ttc = $obj->price_min_ttc; $this->price_base_type = $obj->price_base_type; $this->tva_tx = $obj->tva_tx; //! French VAT NPR $this->tva_npr = $obj->tva_npr; //! Spanish local taxes $this->localtax1_tx = $obj->localtax1_tx; $this->localtax2_tx = $obj->localtax2_tx; $this->finished = $obj->finished; $this->duration = $obj->duration; $this->duration_value = substr($obj->duration, 0, dol_strlen($obj->duration) - 1); $this->duration_unit = substr($obj->duration, -1); $this->canvas = $obj->canvas; $this->weight = $obj->weight; $this->weight_units = $obj->weight_units; $this->length = $obj->length; $this->length_units = $obj->length_units; $this->surface = $obj->surface; $this->surface_units = $obj->surface_units; $this->volume = $obj->volume; $this->volume_units = $obj->volume_units; $this->barcode = $obj->barcode; $this->barcode_type = $obj->fk_barcode_type; $this->accountancy_code_buy = $obj->accountancy_code_buy; $this->accountancy_code_sell = $obj->accountancy_code_sell; $this->seuil_stock_alerte = $obj->seuil_stock_alerte; $this->desiredstock = $obj->desiredstock; $this->stock_reel = $obj->stock; $this->pmp = $obj->pmp; $this->date_creation = $obj->datec; $this->date_modification = $obj->tms; $this->import_key = $obj->import_key; $this->entity = $obj->entity; $this->ref_ext = $obj->ref_ext; $this->fk_price_expression = $obj->fk_price_expression; $this->fk_unit = $obj->fk_unit; $this->db->free($resql); // Retreive all extrafield for current object // fetch optionals attributes and labels require_once DOL_DOCUMENT_ROOT . '/core/class/extrafields.class.php'; $extrafields = new ExtraFields($this->db); $extralabels = $extrafields->fetch_name_optionals_label($this->table_element, true); $this->fetch_optionals($this->id, $extralabels); // multilangs if (!empty($conf->global->MAIN_MULTILANGS)) { $this->getMultiLangs(); } // Load multiprices array if (!empty($conf->global->PRODUIT_MULTIPRICES)) { for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++) { $sql = "SELECT price, price_ttc, price_min, price_min_ttc,"; $sql .= " price_base_type, tva_tx, tosell, price_by_qty, rowid, recuperableonly"; $sql .= " FROM " . MAIN_DB_PREFIX . "product_price"; $sql .= " WHERE entity IN (" . getEntity('productprice', 1) . ")"; $sql .= " AND price_level=" . $i; $sql .= " AND fk_product = '" . $this->id . "'"; $sql .= " ORDER BY date_price DESC"; $sql .= " LIMIT 1"; $resql = $this->db->query($sql); if ($resql) { $result = $this->db->fetch_array($resql); $this->multiprices[$i] = $result["price"]; $this->multiprices_ttc[$i] = $result["price_ttc"]; $this->multiprices_min[$i] = $result["price_min"]; $this->multiprices_min_ttc[$i] = $result["price_min_ttc"]; $this->multiprices_base_type[$i] = $result["price_base_type"]; $this->multiprices_tva_tx[$i] = $result["tva_tx"]; $this->multiprices_recuperableonly[$i] = $result["recuperableonly"]; // Price by quantity $this->prices_by_qty[$i] = $result["price_by_qty"]; $this->prices_by_qty_id[$i] = $result["rowid"]; // Récuperation de la liste des prix selon qty si flag positionné if ($this->prices_by_qty[$i] == 1) { $sql = "SELECT rowid,price, unitprice, quantity, remise_percent, remise"; $sql .= " FROM " . MAIN_DB_PREFIX . "product_price_by_qty"; $sql .= " WHERE fk_product_price = '" . $this->prices_by_qty_id[$i] . "'"; $sql .= " ORDER BY quantity ASC"; $resultat = array(); $resql = $this->db->query($sql); if ($resql) { $ii = 0; while ($result = $this->db->fetch_array($resql)) { $resultat[$ii] = array(); $resultat[$ii]["rowid"] = $result["rowid"]; $resultat[$ii]["price"] = $result["price"]; $resultat[$ii]["unitprice"] = $result["unitprice"]; $resultat[$ii]["quantity"] = $result["quantity"]; $resultat[$ii]["remise_percent"] = $result["remise_percent"]; $resultat[$ii]["remise"] = $result["remise"]; $ii++; } $this->prices_by_qty_list[$i] = $resultat; } else { dol_print_error($this->db); return -1; } } } else { dol_print_error($this->db); return -1; } } } else { if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) { $sql = "SELECT price, price_ttc, price_min, price_min_ttc,"; $sql .= " price_base_type, tva_tx, tosell, price_by_qty, rowid"; $sql .= " FROM " . MAIN_DB_PREFIX . "product_price"; $sql .= " WHERE fk_product = '" . $this->id . "'"; $sql .= " ORDER BY date_price DESC"; $sql .= " LIMIT 1"; $resql = $this->db->query($sql); if ($resql) { $result = $this->db->fetch_array($resql); // Price by quantity $this->prices_by_qty[0] = $result["price_by_qty"]; $this->prices_by_qty_id[0] = $result["rowid"]; // Récuperation de la liste des prix selon qty si flag positionné if ($this->prices_by_qty[0] == 1) { $sql = "SELECT rowid,price, unitprice, quantity, remise_percent, remise"; $sql .= " FROM " . MAIN_DB_PREFIX . "product_price_by_qty"; $sql .= " WHERE fk_product_price = '" . $this->prices_by_qty_id[0] . "'"; $sql .= " ORDER BY quantity ASC"; $resultat = array(); $resql = $this->db->query($sql); if ($resql) { $ii = 0; while ($result = $this->db->fetch_array($resql)) { $resultat[$ii] = array(); $resultat[$ii]["rowid"] = $result["rowid"]; $resultat[$ii]["price"] = $result["price"]; $resultat[$ii]["unitprice"] = $result["unitprice"]; $resultat[$ii]["quantity"] = $result["quantity"]; $resultat[$ii]["remise_percent"] = $result["remise_percent"]; $resultat[$ii]["remise"] = $result["remise"]; $ii++; } $this->prices_by_qty_list[0] = $resultat; } else { dol_print_error($this->db); return -1; } } } else { dol_print_error($this->db); return -1; } } } if (!empty($this->fk_price_expression) && empty($ignore_expression)) { require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php'; $priceparser = new PriceParser($this->db); $price_result = $priceparser->parseProduct($this); if ($price_result >= 0) { $this->price = $price_result; //Calculate the VAT $this->price_ttc = price2num($this->price) * (1 + $this->tva_tx / 100); $this->price_ttc = price2num($this->price_ttc, 'MU'); } } // We should not load stock at each fetch. If someone need stock, he must call load_stock after fetch. //$res=$this->load_stock(); // instead we just init the stock_warehouse array $this->stock_warehouse = array(); return 1; } else { return 0; } } else { dol_print_error($this->db); return -1; } }
$product_static->label = $objp->label; $product_static->type = $objp->fk_product_type; $product_static->entity = $objp->entity; print $product_static->getNomUrl(1, '', 16); print "</td>\n"; print '<td>' . dol_trunc($objp->label, 32) . '</td>'; print "<td>"; print dol_print_date($db->jdate($objp->datem), 'day'); print "</td>"; // Sell price if (empty($conf->global->PRODUIT_MULTIPRICES)) { if (!empty($objp->fk_price_expression)) { $product = new Product($db); $product->fetch($objp->rowid); $priceparser = new PriceParser($db); $price_result = $priceparser->parseProduct($product); if ($price_result >= 0) { $objp->price = $price_result; } } print '<td align="right">'; if (isset($objp->price_base_type) && $objp->price_base_type == 'TTC') { print price($objp->price_ttc) . ' ' . $langs->trans("TTC"); } else { print price($objp->price) . ' ' . $langs->trans("HT"); } print '</td>'; } print '<td align="right" class="nowrap">'; print $product_static->LibStatut($objp->tosell, 5, 0); print "</td>";
{ $error = 0; $pricestoupdate = array(); $psq = GETPOST('psqflag'); $psq = empty($newpsq) ? 0 : $newpsq; $maxpricesupplier = $object->min_recommended_price(); if (!empty($conf->dynamicprices->enabled)) { $object->fk_price_expression = empty($eid) ? 0 : $eid; //0 discards expression if ($object->fk_price_expression != 0) { //Check the expression validity by parsing it $priceparser = new PriceParser($db); if ($priceparser->parseProduct($object) < 0) { $error ++; setEventMessages($priceparser->translatedError(), null, 'errors'); } } } // Multiprices if (!$error && !empty($conf->global->PRODUIT_MULTIPRICES)) { $newprice = GETPOST('price', 'array'); $newprice_min = GETPOST('price_min', 'array'); $newpricebase = GETPOST('multiprices_base_type', 'array'); $newvattx = GETPOST('tva_tx', 'array'); //Shall we generate prices using price rules?
/** * Load data into info_box_contents array to show array later. * * @param int $max Maximum number of records to load * @return void */ function loadBox($max = 5) { global $user, $langs, $db, $conf; $this->max = $max; include_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; $productstatic = new Product($db); $this->info_box_head = array('text' => $langs->trans("BoxTitleProductsAlertStock", $max)); if ($user->rights->produit->lire || $user->rights->service->lire) { $sql = "SELECT p.rowid, p.label, p.price, p.ref, p.price_base_type, p.price_ttc, p.fk_product_type, p.tms, p.tosell, p.tobuy, p.seuil_stock_alerte,"; $sql .= " SUM(" . $db->ifsql("s.reel IS NULL", "0", "s.reel") . ") as total_stock"; $sql .= " FROM " . MAIN_DB_PREFIX . "product as p"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_stock as s on p.rowid = s.fk_product"; $sql .= ' WHERE p.entity IN (' . getEntity($productstatic->element, 1) . ')'; $sql .= " AND p.tosell = 1 AND p.seuil_stock_alerte > 0"; if (empty($user->rights->produit->lire)) { $sql .= ' AND p.fk_product_type != 0'; } if (empty($user->rights->service->lire)) { $sql .= ' AND p.fk_product_type != 1'; } $sql .= " GROUP BY p.rowid, p.ref, p.label, p.price, p.price_base_type, p.price_ttc, p.fk_product_type, p.tms, p.tosell, p.tobuy, p.seuil_stock_alerte"; $sql .= " HAVING SUM(" . $db->ifsql("s.reel IS NULL", "0", "s.reel") . ") < p.seuil_stock_alerte"; $sql .= $db->order('p.seuil_stock_alerte', 'DESC'); $sql .= $db->plimit($max, 0); $result = $db->query($sql); if ($result) { $langs->load("stocks"); $num = $db->num_rows($result); $line = 0; while ($line < $num) { $objp = $db->fetch_object($result); $datem = $db->jdate($objp->tms); // Multilangs if (!empty($conf->global->MAIN_MULTILANGS)) { $sqld = "SELECT label"; $sqld .= " FROM " . MAIN_DB_PREFIX . "product_lang"; $sqld .= " WHERE fk_product=" . $objp->rowid; $sqld .= " AND lang='" . $langs->getDefaultLang() . "'"; $sqld .= " LIMIT 1"; $resultd = $db->query($sqld); if ($resultd) { $objtp = $db->fetch_object($resultd); if (isset($objtp->label) && $objtp->label != '') { $objp->label = $objtp->label; } } } $productstatic->id = $objp->rowid; $productstatic->ref = $objp->ref; $productstatic->type = $objp->fk_product_type; $productstatic->label = $objp->label; $this->info_box_contents[$line][] = array('td' => 'align="left"', 'text' => $productstatic->getNomUrl(1), 'asis' => 1); $this->info_box_contents[$line][] = array('td' => 'align="left"', 'text' => $objp->label); if (empty($objp->fk_price_expression)) { $price_base_type = $langs->trans($objp->price_base_type); $price = $objp->price_base_type == 'HT' ? price($objp->price) : ($price = price($objp->price_ttc)); } else { $productstatic->fetch($objp->rowid, '', '', 1); $priceparser = new PriceParser($this->db); $price_result = $priceparser->parseProduct($productstatic); if ($price_result >= 0) { if ($objp->price_base_type == 'HT') { $price_base_type = $langs->trans("HT"); } else { $price_result = $price_result * (1 + $productstatic->tva_tx / 100); $price_base_type = $langs->trans("TTC"); } $price = price($price_result); } } $this->info_box_contents[$line][] = array('td' => 'align="right"', 'text' => $price); $this->info_box_contents[$line][] = array('td' => 'align="left" class="nowrap"', 'text' => $price_base_type); $this->info_box_contents[$line][] = array('td' => 'align="center"', 'text' => $objp->total_stock . ' / ' . $objp->seuil_stock_alerte, 'text2' => img_warning($langs->transnoentitiesnoconv("StockLowerThanLimit"))); $this->info_box_contents[$line][] = array('td' => 'align="right" width="18"', 'text' => $productstatic->LibStatut($objp->tosell, 3, 0)); $this->info_box_contents[$line][] = array('td' => 'align="right" width="18"', 'text' => $productstatic->LibStatut($objp->tobuy, 3, 1)); $line++; } if ($num == 0) { $this->info_box_contents[$line][0] = array('td' => 'align="center"', 'text' => $langs->trans("NoTooLowStockProducts")); } $db->free($result); } else { $this->info_box_contents[0][0] = array('td' => 'align="left"', 'maxlength' => 500, 'text' => $db->error() . ' sql=' . $sql); } } else { $this->info_box_contents[0][0] = array('td' => 'align="left"', 'text' => $langs->trans("ReadPermissionNotAllowed")); } }
/** * Return list of products for a customer * * @param int $selected Preselected product * @param string $htmlname Name of select html * @param string $filtertype Filter on product type (''=nofilter, 0=product, 1=service) * @param int $limit Limit on number of returned lines * @param int $price_level Level of price to show * @param string $filterkey Filter on product * @param int $status -1=Return all products, 0=Products not on sell, 1=Products on sell * @param int $finished Filter on finished field: 2=No filter * @param int $outputmode 0=HTML select string, 1=Array * @param int $socid Thirdparty Id * @return array Array of keys for json */ function select_produits_list($selected = '', $htmlname = 'productid', $filtertype = '', $limit = 20, $price_level = 0, $filterkey = '', $status = 1, $finished = 2, $outputmode = 0, $socid = 0) { global $langs, $conf, $user, $db; $out = ''; $outarray = array(); $sql = "SELECT "; $sql .= " p.rowid, p.label, p.ref, p.description, p.fk_product_type, p.price, p.price_ttc, p.price_base_type, p.tva_tx, p.duration, p.stock, p.fk_price_expression"; //Price by customer if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) { $sql .= ' ,pcp.rowid as idprodcustprice, pcp.price as custprice, pcp.price_ttc as custprice_ttc,'; $sql .= ' pcp.price_base_type as custprice_base_type, pcp.tva_tx as custtva_tx'; } // Multilang : we add translation if (!empty($conf->global->MAIN_MULTILANGS)) { $sql .= ", pl.label as label_translated"; } // Price by quantity if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) { $sql .= ", (SELECT pp.rowid FROM " . MAIN_DB_PREFIX . "product_price as pp WHERE pp.fk_product = p.rowid"; if ($price_level >= 1 && !empty($conf->global->PRODUIT_MULTIPRICES)) { $sql .= " AND price_level=" . $price_level; } $sql .= " ORDER BY date_price"; $sql .= " DESC LIMIT 1) as price_rowid"; $sql .= ", (SELECT pp.price_by_qty FROM " . MAIN_DB_PREFIX . "product_price as pp WHERE pp.fk_product = p.rowid"; if ($price_level >= 1 && !empty($conf->global->PRODUIT_MULTIPRICES)) { $sql .= " AND price_level=" . $price_level; } $sql .= " ORDER BY date_price"; $sql .= " DESC LIMIT 1) as price_by_qty"; } $sql .= " FROM " . MAIN_DB_PREFIX . "product as p"; //Price by customer if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) { $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_customer_price as pcp ON pcp.fk_soc=" . $socid . " AND pcp.fk_product=p.rowid"; } // Multilang : we add translation if (!empty($conf->global->MAIN_MULTILANGS)) { $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_lang as pl ON pl.fk_product = p.rowid AND pl.lang='" . $langs->getDefaultLang() . "'"; } $sql .= ' WHERE p.entity IN (' . getEntity('product', 1) . ')'; if ($finished == 0) { $sql .= " AND p.finished = " . $finished; } elseif ($finished == 1) { $sql .= " AND p.finished = " . $finished; if ($status >= 0) { $sql .= " AND p.tosell = " . $status; } } elseif ($status >= 0) { $sql .= " AND p.tosell = " . $status; } if (strval($filtertype) != '') { $sql .= " AND p.fk_product_type=" . $filtertype; } // Add criteria on ref/label if ($filterkey != '') { $sql .= ' AND ('; $prefix = empty($conf->global->PRODUCT_DONOTSEARCH_ANYWHERE) ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on // For natural search $scrit = explode(' ', $filterkey); $i = 0; if (count($scrit) > 1) { $sql .= "("; } foreach ($scrit as $crit) { if ($i > 0) { $sql .= " AND "; } $sql .= "(p.ref LIKE '" . $db->escape($prefix . $crit) . "%' OR p.label LIKE '" . $db->escape($prefix . $crit) . "%'"; if (!empty($conf->global->MAIN_MULTILANGS)) { $sql .= " OR pl.label LIKE '" . $db->escape($prefix . $crit) . "%'"; } $sql .= ")"; $i++; } if (count($scrit) > 1) { $sql .= ")"; } if (!empty($conf->barcode->enabled)) { $sql .= " OR p.barcode LIKE '" . $db->escape($prefix . $filterkey) . "%'"; } $sql .= ')'; } $sql .= $db->order("p.ref"); $sql .= $db->plimit($limit); // Build output string dol_syslog(get_class($this) . "::select_produits_list search product", LOG_DEBUG); $result = $this->db->query($sql); if ($result) { require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php'; $num = $this->db->num_rows($result); $out .= '<select class="flat" name="' . $htmlname . '" id="' . $htmlname . '">'; $out .= '<option value="0" selected> </option>'; $i = 0; while ($num && $i < $num) { $opt = ''; $optJson = array(); $objp = $this->db->fetch_object($result); if (!empty($objp->price_by_qty) && $objp->price_by_qty == 1 && !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) { // Price by quantity will return many prices for the same product $sql = "SELECT rowid, quantity, price, unitprice, remise_percent, remise"; $sql .= " FROM " . MAIN_DB_PREFIX . "product_price_by_qty"; $sql .= " WHERE fk_product_price=" . $objp->price_rowid; $sql .= " ORDER BY quantity ASC"; dol_syslog(get_class($this) . "::select_produits_list search price by qty", LOG_DEBUG); $result2 = $this->db->query($sql); if ($result2) { $nb_prices = $this->db->num_rows($result2); $j = 0; while ($nb_prices && $j < $nb_prices) { $objp2 = $this->db->fetch_object($result2); $objp->quantity = $objp2->quantity; $objp->price = $objp2->price; $objp->unitprice = $objp2->unitprice; $objp->remise_percent = $objp2->remise_percent; $objp->remise = $objp2->remise; $objp->price_by_qty_rowid = $objp2->rowid; $this->constructProductListOption($objp, $opt, $optJson, 0, $selected); $j++; // Add new entry // "key" value of json key array is used by jQuery automatically as selected value // "label" value of json key array is used by jQuery automatically as text for combo box $out .= $opt; array_push($outarray, $optJson); } } } else { if (!empty($objp->fk_price_expression)) { $price_product = new Product($this->db); $price_product->fetch($objp->rowid, '', '', 1); $priceparser = new PriceParser($this->db); $price_result = $priceparser->parseProduct($price_product); if ($price_result >= 0) { $objp->price = $price_result; $objp->unitprice = $price_result; //Calculate the VAT $objp->price_ttc = price2num($objp->price) * (1 + $objp->tva_tx / 100); $objp->price_ttc = price2num($objp->price_ttc, 'MU'); } } $this->constructProductListOption($objp, $opt, $optJson, $price_level, $selected); // Add new entry // "key" value of json key array is used by jQuery automatically as selected value // "label" value of json key array is used by jQuery automatically as text for combo box $out .= $opt; array_push($outarray, $optJson); } $i++; } $out .= '</select>'; $this->db->free($result); if (empty($outputmode)) { return $out; } return $outarray; } else { dol_print_error($db); } }