fournisseur.product.class.php 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  1. <?php
  2. /* Copyright (C) 2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2006-2011 Laurent Destailleur <eldy@users.sourceforge.net>
  4. * Copyright (C) 2009-2014 Regis Houssin <regis.houssin@capnetworks.com>
  5. * Copyright (C) 2011 Juanjo Menent <jmenent@2byte.es>
  6. * Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
  7. * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
  8. * Copyright (C) 2016 Charlie Benke <charlie@patas-monkey.com>
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 3 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. */
  23. /**
  24. * \file htdocs/fourn/class/fournisseur.product.class.php
  25. * \ingroup produit
  26. * \brief File of class to manage predefined suppliers products
  27. */
  28. require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
  29. require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php';
  30. require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
  31. /**
  32. * Class to manage predefined suppliers products
  33. */
  34. class ProductFournisseur extends Product
  35. {
  36. var $db;
  37. var $error;
  38. var $product_fourn_price_id; // id of ligne product-supplier
  39. var $id; // product id
  40. /**
  41. * @deprecated
  42. * @see ref_supplier
  43. */
  44. var $fourn_ref;
  45. var $delivery_time_days;
  46. var $ref_supplier; // ref supplier (can be set by get_buyprice)
  47. var $vatrate_supplier; // default vat rate for this supplier/qty/product (can be set by get_buyprice)
  48. var $fourn_id; //supplier id
  49. var $fourn_qty; // quantity for price (can be set by get_buyprice)
  50. var $fourn_pu; // unit price for quantity (can be set by get_buyprice)
  51. var $fourn_price; // price for quantity
  52. var $fourn_remise_percent; // discount for quantity (percent)
  53. var $fourn_remise; // discount for quantity (amount)
  54. var $product_fourn_id; // supplier id
  55. var $fk_availability; // availability delay - visible/used if option FOURN_PRODUCT_AVAILABILITY is on (duplicate information compared to delivery delay)
  56. var $fourn_unitprice;
  57. var $fourn_tva_tx;
  58. var $fourn_tva_npr;
  59. /**
  60. * @deprecated
  61. */
  62. var $fourn_unitcharges; // old version used a buggy system to calculate margin of a charge field on supplier price. Now margin is on pmp, best supplier price or cost price.
  63. var $fk_supplier_price_expression;
  64. /**
  65. * Constructor
  66. *
  67. * @param DoliDB $db Database handler
  68. */
  69. function __construct($db)
  70. {
  71. $this->db = $db;
  72. }
  73. /**
  74. * Remove all prices for this couple supplier-product
  75. *
  76. * @param int $id_fourn Supplier Id
  77. * @return int < 0 if error, > 0 if ok
  78. */
  79. function remove_fournisseur($id_fourn)
  80. {
  81. $ok=1;
  82. $this->db->begin();
  83. $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_fournisseur_price";
  84. $sql.= " WHERE fk_product = ".$this->id." AND fk_soc = ".$id_fourn;
  85. dol_syslog(get_class($this)."::remove_fournisseur", LOG_DEBUG);
  86. $resql2=$this->db->query($sql);
  87. if (! $resql2)
  88. {
  89. $this->error=$this->db->lasterror();
  90. $ok=0;
  91. }
  92. if ($ok)
  93. {
  94. $this->db->commit();
  95. return 1;
  96. }
  97. else
  98. {
  99. $this->db->rollback();
  100. return -1;
  101. }
  102. }
  103. /**
  104. * Remove a price for a couple supplier-product
  105. *
  106. * @param int $rowid Line id of price
  107. * @return int <0 if KO, >0 if OK
  108. */
  109. function remove_product_fournisseur_price($rowid)
  110. {
  111. global $conf, $user;
  112. $error=0;
  113. $this->db->begin();
  114. // Call trigger
  115. $result=$this->call_trigger('SUPPLIER_PRODUCT_BUYPRICE_DELETE',$user);
  116. if ($result < 0) $error++;
  117. // End call triggers
  118. if (empty($error))
  119. {
  120. $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_fournisseur_price";
  121. $sql.= " WHERE rowid = ".$rowid;
  122. dol_syslog(get_class($this)."::remove_product_fournisseur_price", LOG_DEBUG);
  123. $resql = $this->db->query($sql);
  124. if (!$resql)
  125. {
  126. $this->error=$this->db->lasterror();
  127. $error++;
  128. }
  129. }
  130. if (empty($error)){
  131. $this->db->commit();
  132. return 1;
  133. }else{
  134. $this->db->rollback();
  135. return -1;
  136. }
  137. }
  138. /**
  139. * Modify the purchase price for a supplier
  140. *
  141. * @param int $qty Min quantity for which price is valid
  142. * @param float $buyprice Purchase price for the quantity min
  143. * @param User $user Object user user made changes
  144. * @param string $price_base_type HT or TTC
  145. * @param Societe $fourn Supplier
  146. * @param int $availability Product availability
  147. * @param string $ref_fourn Supplier ref
  148. * @param float $tva_tx VAT rate
  149. * @param string $charges costs affering to product
  150. * @param float $remise_percent Discount regarding qty (percent)
  151. * @param float $remise Discount regarding qty (amount)
  152. * @param int $newnpr Set NPR or not
  153. * @param int $delivery_time_days Delay in days for delivery (max). May be '' if not defined.
  154. * @param string $supplier_reputation Reputation with this product to the defined supplier (empty, FAVORITE, DONOTORDER)
  155. * @return int <0 if KO, >=0 if OK
  156. */
  157. function update_buyprice($qty, $buyprice, $user, $price_base_type, $fourn, $availability, $ref_fourn, $tva_tx, $charges=0, $remise_percent=0, $remise=0, $newnpr=0, $delivery_time_days=0, $supplier_reputation='')
  158. {
  159. global $conf, $langs;
  160. //global $mysoc;
  161. // Clean parameter
  162. if (empty($qty)) $qty=0;
  163. if (empty($buyprice)) $buyprice=0;
  164. if (empty($charges)) $charges=0;
  165. if (empty($availability)) $availability=0;
  166. if (empty($remise_percent)) $remise_percent=0;
  167. if (empty($supplier_reputation) || $supplier_reputation == -1) $supplier_reputation='';
  168. if ($delivery_time_days != '' && ! is_numeric($delivery_time_days)) $delivery_time_days = '';
  169. if ($price_base_type == 'TTC')
  170. {
  171. $ttx = $tva_tx;
  172. $buyprice = $buyprice/(1+($ttx/100));
  173. }
  174. $buyprice=price2num($buyprice,'MU');
  175. $charges=price2num($charges,'MU');
  176. $qty=price2num($qty);
  177. $error=0;
  178. $unitBuyPrice = price2num($buyprice/$qty,'MU');
  179. $unitCharges = price2num($charges/$qty,'MU');
  180. $now=dol_now();
  181. $this->db->begin();
  182. if ($this->product_fourn_price_id > 0)
  183. {
  184. $sql = "UPDATE ".MAIN_DB_PREFIX."product_fournisseur_price";
  185. $sql.= " SET fk_user = " . $user->id." ,";
  186. $sql.= " ref_fourn = '" . $this->db->escape($ref_fourn) . "',";
  187. $sql.= " price = ".price2num($buyprice).",";
  188. $sql.= " quantity = ".$qty.",";
  189. $sql.= " remise_percent = ".$remise_percent.",";
  190. $sql.= " remise = ".$remise.",";
  191. $sql.= " unitprice = ".$unitBuyPrice.",";
  192. $sql.= " unitcharges = ".$unitCharges.",";
  193. $sql.= " tva_tx = ".$tva_tx.",";
  194. $sql.= " fk_availability = ".$availability.",";
  195. $sql.= " entity = ".$conf->entity.",";
  196. $sql.= " info_bits = ".$newnpr.",";
  197. $sql.= " charges = ".$charges.",";
  198. $sql.= " delivery_time_days = ".($delivery_time_days != '' ? $delivery_time_days : 'null').",";
  199. $sql.= " supplier_reputation = ".(empty($supplier_reputation) ? 'NULL' : "'".$this->db->escape($supplier_reputation)."'");
  200. $sql.= " WHERE rowid = ".$this->product_fourn_price_id;
  201. // TODO Add price_base_type and price_ttc
  202. dol_syslog(get_class($this).'::update_buyprice update knowing id of line = product_fourn_price_id = '.$this->product_fourn_price_id, LOG_DEBUG);
  203. $resql = $this->db->query($sql);
  204. if ($resql)
  205. {
  206. // Call trigger
  207. $result=$this->call_trigger('SUPPLIER_PRODUCT_BUYPRICE_UPDATE',$user);
  208. if ($result < 0) $error++;
  209. // End call triggers
  210. if (empty($error))
  211. {
  212. $this->db->commit();
  213. return $this->product_fourn_price_id;
  214. }
  215. else
  216. {
  217. $this->db->rollback();
  218. return -1;
  219. }
  220. }
  221. else
  222. {
  223. $this->error=$this->db->error()." sql=".$sql;
  224. $this->db->rollback();
  225. return -2;
  226. }
  227. }
  228. else
  229. {
  230. dol_syslog(get_class($this) . '::update_buyprice without knowing id of line, so we delete from company, quantity and supplier_ref and insert again', LOG_DEBUG);
  231. // Delete price for this quantity
  232. $sql = "DELETE FROM " . MAIN_DB_PREFIX . "product_fournisseur_price";
  233. $sql .= " WHERE fk_soc = " . $fourn->id . " AND ref_fourn = '" . $this->db->escape($ref_fourn) . "' AND quantity = " . $qty . " AND entity = " . $conf->entity;
  234. $resql = $this->db->query($sql);
  235. if ($resql) {
  236. // Add price for this quantity to supplier
  237. $sql = "INSERT INTO " . MAIN_DB_PREFIX . "product_fournisseur_price(";
  238. $sql .= "datec, fk_product, fk_soc, ref_fourn, fk_user, price, quantity, remise_percent, remise, unitprice, tva_tx, charges, unitcharges, fk_availability, info_bits, entity, delivery_time_days,supplier_reputation)";
  239. $sql .= " values('" . $this->db->idate($now) . "',";
  240. $sql .= " " . $this->id . ",";
  241. $sql .= " " . $fourn->id . ",";
  242. $sql .= " '" . $this->db->escape($ref_fourn) . "',";
  243. $sql .= " " . $user->id . ",";
  244. $sql .= " " . $buyprice . ",";
  245. $sql .= " " . $qty . ",";
  246. $sql .= " " . $remise_percent . ",";
  247. $sql .= " " . $remise . ",";
  248. $sql .= " " . $unitBuyPrice . ",";
  249. $sql .= " " . $tva_tx . ",";
  250. $sql .= " " . $charges . ",";
  251. $sql .= " " . $unitCharges . ",";
  252. $sql .= " " . $availability . ",";
  253. $sql .= " " . $newnpr . ",";
  254. $sql .= $conf->entity . ",";
  255. $sql .= $delivery_time_days . ",";
  256. $sql .= (empty($supplier_reputation) ? 'NULL' : "'" . $this->db->escape($supplier_reputation) . "'");
  257. $sql .= ")";
  258. $idinserted = 0;
  259. $resql = $this->db->query($sql);
  260. if ($resql) {
  261. $idinserted = $this->db->last_insert_id(MAIN_DB_PREFIX . "product_fournisseur_price");
  262. }
  263. else {
  264. $error++;
  265. }
  266. if (! $error && ! empty($conf->global->PRODUCT_PRICE_SUPPLIER_NO_LOG)) {
  267. // Add record into log table
  268. $sql = "INSERT INTO " . MAIN_DB_PREFIX . "product_fournisseur_price_log(";
  269. $sql .= "datec, fk_product_fournisseur,fk_user,price,quantity)";
  270. $sql .= "values('" . $this->db->idate($now) . "',";
  271. $sql .= " " . $this->product_fourn_id . ",";
  272. $sql .= " " . $user->id . ",";
  273. $sql .= " " . price2num($buyprice) . ",";
  274. $sql .= " " . $qty;
  275. $sql .= ")";
  276. $resql = $this->db->query($sql);
  277. if (! $resql) {
  278. $error++;
  279. }
  280. }
  281. if (! $error) {
  282. // Call trigger
  283. $result = $this->call_trigger('SUPPLIER_PRODUCT_BUYPRICE_CREATE', $user);
  284. if ($result < 0)
  285. $error++;
  286. // End call triggers
  287. if (empty($error)) {
  288. $this->db->commit();
  289. return $idinserted;
  290. } else {
  291. $this->db->rollback();
  292. return -1;
  293. }
  294. } else {
  295. $this->error = $this->db->lasterror() . " sql=" . $sql;
  296. $this->db->rollback();
  297. return -2;
  298. }
  299. } else {
  300. $this->error = $this->db->lasterror() . " sql=" . $sql;
  301. $this->db->rollback();
  302. return - 1;
  303. }
  304. }
  305. }
  306. /**
  307. * Loads the price information of a provider
  308. *
  309. * @param int $rowid Line id
  310. * @param int $ignore_expression Ignores the math expression for calculating price and uses the db value instead
  311. * @return int < 0 if KO, 0 if OK but not found, > 0 if OK
  312. */
  313. function fetch_product_fournisseur_price($rowid, $ignore_expression = 0)
  314. {
  315. global $conf;
  316. $sql = "SELECT pfp.rowid, pfp.price, pfp.quantity, pfp.unitprice, pfp.remise_percent, pfp.remise, pfp.tva_tx, pfp.fk_availability,";
  317. $sql.= " pfp.fk_soc, pfp.ref_fourn, pfp.fk_product, pfp.charges, pfp.unitcharges, pfp.fk_supplier_price_expression, pfp.delivery_time_days,"; // , pfp.recuperableonly as fourn_tva_npr"; FIXME this field not exist in llx_product_fournisseur_price
  318. $sql.=" pfp.supplier_reputation";
  319. $sql.= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price as pfp";
  320. $sql.= " WHERE pfp.rowid = ".$rowid;
  321. dol_syslog(get_class($this)."::fetch_product_fournisseur_price", LOG_DEBUG);
  322. $resql = $this->db->query($sql);
  323. if ($resql)
  324. {
  325. $obj = $this->db->fetch_object($resql);
  326. if ($obj)
  327. {
  328. $this->product_fourn_price_id = $rowid;
  329. $this->id = $obj->fk_product;
  330. $this->fk_product = $obj->fk_product;
  331. $this->product_id = $obj->fk_product; // deprecated
  332. $this->fourn_id = $obj->fk_soc;
  333. $this->fourn_ref = $obj->ref_fourn; // deprecated
  334. $this->ref_supplier = $obj->ref_fourn;
  335. $this->fourn_price = $obj->price;
  336. $this->fourn_charges = $obj->charges; // deprecated
  337. $this->fourn_qty = $obj->quantity;
  338. $this->fourn_remise_percent = $obj->remise_percent;
  339. $this->fourn_remise = $obj->remise;
  340. $this->fourn_unitprice = $obj->unitprice;
  341. $this->fourn_unitcharges = $obj->unitcharges; // deprecated
  342. $this->fourn_tva_tx = $obj->tva_tx;
  343. //$this->fourn_tva_npr = $obj->fourn_tva_npr; // TODO this field not exist in llx_product_fournisseur_price. We should add it ?
  344. $this->fk_availability = $obj->fk_availability;
  345. $this->delivery_time_days = $obj->delivery_time_days;
  346. $this->fk_supplier_price_expression = $obj->fk_supplier_price_expression;
  347. $this->supplier_reputation = $obj->supplier_reputation;
  348. if (empty($ignore_expression) && !empty($this->fk_supplier_price_expression))
  349. {
  350. $priceparser = new PriceParser($this->db);
  351. $price_result = $priceparser->parseProductSupplier($this->fk_product, $this->fk_supplier_price_expression, $this->fourn_qty, $this->fourn_tva_tx);
  352. if ($price_result >= 0) {
  353. $this->fourn_price = $price_result;
  354. //recalculation of unitprice, as probably the price changed...
  355. if ($this->fourn_qty!=0)
  356. {
  357. $this->fourn_unitprice = price2num($this->fourn_price/$this->fourn_qty,'MU');
  358. }
  359. else
  360. {
  361. $this->fourn_unitprice="";
  362. }
  363. }
  364. }
  365. return 1;
  366. }
  367. else
  368. {
  369. return 0;
  370. }
  371. }
  372. else
  373. {
  374. $this->error=$this->db->error();
  375. return -1;
  376. }
  377. }
  378. /**
  379. * List all supplier prices of a product
  380. *
  381. * @param int $prodid Id of product
  382. * @param string $sortfield Sort field
  383. * @param string $sortorder Sort order
  384. * @return array Array of Products with new properties to define supplier price
  385. */
  386. function list_product_fournisseur_price($prodid, $sortfield='', $sortorder='')
  387. {
  388. global $conf;
  389. $sql = "SELECT s.nom as supplier_name, s.rowid as fourn_id,";
  390. $sql.= " pfp.rowid as product_fourn_pri_id, pfp.ref_fourn, pfp.fk_product as product_fourn_id, pfp.fk_supplier_price_expression,";
  391. $sql.= " pfp.price, pfp.quantity, pfp.unitprice, pfp.remise_percent, pfp.remise, pfp.tva_tx, pfp.fk_availability, pfp.charges, pfp.unitcharges, pfp.info_bits, pfp.delivery_time_days, pfp.supplier_reputation";
  392. $sql.= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price as pfp";
  393. $sql.= ", ".MAIN_DB_PREFIX."societe as s";
  394. $sql.= " WHERE pfp.entity IN (".getEntity('productprice', 1).")";
  395. $sql.= " AND pfp.fk_soc = s.rowid";
  396. $sql.= " AND s.status=1"; // only enabled company selected
  397. $sql.= " AND pfp.fk_product = ".$prodid;
  398. if (empty($sortfield)) $sql.= " ORDER BY s.nom, pfp.quantity, pfp.price";
  399. else $sql.= $this->db->order($sortfield,$sortorder);
  400. dol_syslog(get_class($this)."::list_product_fournisseur_price", LOG_DEBUG);
  401. $resql = $this->db->query($sql);
  402. if ($resql)
  403. {
  404. $retarray = array();
  405. while ($record = $this->db->fetch_array($resql))
  406. {
  407. //define base attribute
  408. $prodfourn = new ProductFournisseur($this->db);
  409. $prodfourn->product_fourn_price_id = $record["product_fourn_pri_id"];
  410. $prodfourn->product_fourn_id = $record["product_fourn_id"];
  411. $prodfourn->fourn_ref = $record["ref_fourn"];
  412. $prodfourn->ref_supplier = $record["ref_fourn"];
  413. $prodfourn->fourn_price = $record["price"];
  414. $prodfourn->fourn_qty = $record["quantity"];
  415. $prodfourn->fourn_remise_percent = $record["remise_percent"];
  416. $prodfourn->fourn_remise = $record["remise"];
  417. $prodfourn->fourn_unitprice = $record["unitprice"];
  418. $prodfourn->fourn_charges = $record["charges"]; // deprecated
  419. $prodfourn->fourn_unitcharges = $record["unitcharges"]; // deprecated
  420. $prodfourn->fourn_tva_tx = $record["tva_tx"];
  421. $prodfourn->fourn_id = $record["fourn_id"];
  422. $prodfourn->fourn_name = $record["supplier_name"];
  423. $prodfourn->fk_availability = $record["fk_availability"];
  424. $prodfourn->delivery_time_days = $record["delivery_time_days"];
  425. $prodfourn->id = $prodid;
  426. $prodfourn->fourn_tva_npr = $record["info_bits"];
  427. $prodfourn->fk_supplier_price_expression = $record["fk_supplier_price_expression"];
  428. $prodfourn->supplier_reputation = $record["supplier_reputation"];
  429. if (!empty($conf->dynamicprices->enabled) && !empty($prodfourn->fk_supplier_price_expression)) {
  430. $priceparser = new PriceParser($this->db);
  431. $price_result = $priceparser->parseProductSupplier($prodfourn);
  432. if ($price_result >= 0) {
  433. $prodfourn->fourn_price = $price_result;
  434. $prodfourn->fourn_unitprice = null; //force recalculation of unitprice, as probably the price changed...
  435. }
  436. }
  437. if (!isset($prodfourn->fourn_unitprice))
  438. {
  439. if ($prodfourn->fourn_qty!=0)
  440. {
  441. $prodfourn->fourn_unitprice = price2num($prodfourn->fourn_price/$prodfourn->fourn_qty,'MU');
  442. }
  443. else
  444. {
  445. $prodfourn->fourn_unitprice="";
  446. }
  447. }
  448. $retarray[]=$prodfourn;
  449. }
  450. $this->db->free($resql);
  451. return $retarray;
  452. }
  453. else
  454. {
  455. $this->error=$this->db->error();
  456. return -1;
  457. }
  458. }
  459. /**
  460. * Load properties for minimum price
  461. *
  462. * @param int $prodid Product id
  463. * @param int $qty Minimum quantity
  464. * @return int <0 if KO, 0=Not found of no product id provided, >0 if OK
  465. */
  466. function find_min_price_product_fournisseur($prodid, $qty=0)
  467. {
  468. global $conf;
  469. if (empty($prodid))
  470. {
  471. dol_syslog("Warning function find_min_price_product_fournisseur were called with prodid empty. May be a bug.", LOG_WARNING);
  472. return 0;
  473. }
  474. $this->product_fourn_price_id = '';
  475. $this->product_fourn_id = '';
  476. $this->fourn_ref = '';
  477. $this->fourn_price = '';
  478. $this->fourn_qty = '';
  479. $this->fourn_remise_percent = '';
  480. $this->fourn_remise = '';
  481. $this->fourn_unitprice = '';
  482. $this->fourn_id = '';
  483. $this->fourn_name = '';
  484. $this->delivery_time_days = '';
  485. $this->id = '';
  486. $sql = "SELECT s.nom as supplier_name, s.rowid as fourn_id,";
  487. $sql.= " pfp.rowid as product_fourn_price_id, pfp.ref_fourn,";
  488. $sql.= " pfp.price, pfp.quantity, pfp.unitprice, pfp.tva_tx, pfp.charges, pfp.unitcharges, ";
  489. $sql.= " pfp.remise, pfp.remise_percent, pfp.fk_supplier_price_expression, pfp.delivery_time_days";
  490. $sql.= " FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."product_fournisseur_price as pfp";
  491. $sql.= " WHERE s.entity IN (".getEntity('societe', 1).")";
  492. $sql.= " AND pfp.fk_product = ".$prodid;
  493. $sql.= " AND pfp.fk_soc = s.rowid";
  494. $sql.= " AND s.status = 1"; // only enabled society
  495. if ($qty > 0) $sql.= " AND pfp.quantity <= ".$qty;
  496. dol_syslog(get_class($this)."::find_min_price_product_fournisseur", LOG_DEBUG);
  497. $resql = $this->db->query($sql);
  498. if ($resql)
  499. {
  500. $record_array = array();
  501. //Store each record to array for later search of min
  502. while ($record = $this->db->fetch_array($resql))
  503. {
  504. $record_array[]=$record;
  505. }
  506. if (count($record_array) == 0)
  507. {
  508. $this->db->free($resql);
  509. return 0;
  510. }
  511. else
  512. {
  513. $min = -1;
  514. foreach($record_array as $record)
  515. {
  516. $fourn_price = $record["price"];
  517. $fourn_unitprice = $record["unitprice"];
  518. if (!empty($conf->dynamicprices->enabled) && !empty($record["fk_supplier_price_expression"])) {
  519. $prod_supplier = new ProductFournisseur($this->db);
  520. $prod_supplier->product_fourn_price_id = $record["product_fourn_price_id"];
  521. $prod_supplier->id = $prodid;
  522. $prod_supplier->fourn_qty = $record["quantity"];
  523. $prod_supplier->fourn_tva_tx = $record["tva_tx"];
  524. $prod_supplier->fk_supplier_price_expression = $record["fk_supplier_price_expression"];
  525. $priceparser = new PriceParser($this->db);
  526. $price_result = $priceparser->parseProductSupplier($prod_supplier);
  527. if ($price_result >= 0) {
  528. $fourn_price = price2num($price_result,'MU');
  529. if ($record["quantity"] != 0)
  530. {
  531. $fourn_unitprice = price2num($fourn_price/$record["quantity"],'MU');
  532. }
  533. else
  534. {
  535. $fourn_unitprice = $fourn_price;
  536. }
  537. }
  538. }
  539. if ($fourn_unitprice < $min || $min == -1)
  540. {
  541. $this->product_fourn_price_id = $record["product_fourn_price_id"];
  542. $this->ref_supplier = $record["ref_fourn"];
  543. $this->ref_fourn = $record["ref_fourn"]; // deprecated
  544. $this->fourn_ref = $record["ref_fourn"]; // deprecated
  545. $this->fourn_price = $fourn_price;
  546. $this->fourn_qty = $record["quantity"];
  547. $this->fourn_remise_percent = $record["remise_percent"];
  548. $this->fourn_remise = $record["remise"];
  549. $this->fourn_unitprice = $fourn_unitprice;
  550. $this->fourn_charges = $record["charges"]; // deprecated
  551. $this->fourn_unitcharges = $record["unitcharges"]; // deprecated
  552. $this->fourn_tva_tx = $record["tva_tx"];
  553. $this->fourn_id = $record["fourn_id"];
  554. $this->fourn_name = $record["supplier_name"];
  555. $this->delivery_time_days = $record["delivery_time_days"];
  556. $this->fk_supplier_price_expression = $record["fk_supplier_price_expression"];
  557. $this->id = $prodid;
  558. $min = $this->fourn_unitprice;
  559. }
  560. }
  561. }
  562. $this->db->free($resql);
  563. return 1;
  564. }
  565. else
  566. {
  567. $this->error=$this->db->error();
  568. return -1;
  569. }
  570. }
  571. /**
  572. * Sets the supplier price expression
  573. *
  574. * @param int $expression_id Expression
  575. * @return int <0 if KO, >0 if OK
  576. */
  577. function setSupplierPriceExpression($expression_id)
  578. {
  579. global $conf;
  580. // Clean parameters
  581. $this->db->begin();
  582. $expression_id = $expression_id != 0 ? $expression_id : 'NULL';
  583. $sql = "UPDATE ".MAIN_DB_PREFIX."product_fournisseur_price";
  584. $sql.= " SET fk_supplier_price_expression = ".$expression_id;
  585. $sql.= " WHERE rowid = ".$this->product_fourn_price_id;
  586. dol_syslog(get_class($this)."::setSupplierPriceExpression", LOG_DEBUG);
  587. $resql = $this->db->query($sql);
  588. if ($resql)
  589. {
  590. $this->db->commit();
  591. return 1;
  592. }
  593. else
  594. {
  595. $this->error=$this->db->error()." sql=".$sql;
  596. $this->db->rollback();
  597. return -1;
  598. }
  599. }
  600. /**
  601. * Display supplier of product
  602. *
  603. * @param int $withpicto Add picto
  604. * @param string $option Target of link ('', 'customer', 'prospect', 'supplier')
  605. * @param int $maxlen Max length of name
  606. * @param integer $notooltip 1=Disable tooltip
  607. * @return string String with supplier price
  608. * TODO Remove this method. Use getNomUrl directly.
  609. */
  610. function getSocNomUrl($withpicto=0,$option='supplier',$maxlen=0,$notooltip=0)
  611. {
  612. $thirdparty = new Fournisseur($this->db);
  613. $thirdparty->fetch($this->fourn_id);
  614. return $thirdparty->getNomUrl($withpicto,$option,$maxlen,$notooltip);
  615. }
  616. /**
  617. * Display price of product
  618. *
  619. * @param int $showunitprice Show "Unit price" into output string
  620. * @param int $showsuptitle Show "Supplier" into output string
  621. * @param int $maxlen Max length of name
  622. * @param integer $notooltip 1=Disable tooltip
  623. * @return string String with supplier price
  624. */
  625. function display_price_product_fournisseur($showunitprice=1,$showsuptitle=1,$maxlen=0,$notooltip=0)
  626. {
  627. global $langs;
  628. $langs->load("suppliers");
  629. $out=($showunitprice?price($this->fourn_unitprice * (1 - $this->fourn_remise_percent/100) + $this->fourn_unitcharges - $this->fourn_remise).' '.$langs->trans("HT").' &nbsp; (':'').($showsuptitle?$langs->trans("Supplier").': ':'').$this->getSocNomUrl(1, 'supplier', $maxlen, $notooltip).' / '.$langs->trans("SupplierRef").': '.$this->fourn_ref.($showunitprice?')':'');
  630. return $out;
  631. }
  632. /**
  633. * Function used to replace a thirdparty id with another one.
  634. *
  635. * @param DoliDB $db Database handler
  636. * @param int $origin_id Old thirdparty id
  637. * @param int $dest_id New thirdparty id
  638. * @return bool
  639. */
  640. public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
  641. {
  642. $tables = array(
  643. 'product_fournisseur_price'
  644. );
  645. return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
  646. }
  647. }