[ Index ] |
|
Code source de Dolibarr 2.0.1 |
1 <?php 2 /* Copyright (C) 2001-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org> 3 * Copyright (C) 2004-2005 Laurent Destailleur <eldy@users.sourceforge.net> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 * 19 * $Id: product.class.php,v 1.63.2.1 2005/12/25 01:39:31 eldy Exp $ 20 * $Source: /cvsroot/dolibarr/dolibarr/htdocs/product.class.php,v $ 21 */ 22 23 /** 24 \file htdocs/product.class.php 25 \ingroup produit 26 \brief Fichier de la classe des produits prédéfinis 27 \version $Revision: 1.63.2.1 $ 28 */ 29 30 31 /** 32 \class Product 33 \brief Classe permettant la gestion des produits prédéfinis 34 */ 35 36 class Product 37 { 38 var $db ; 39 40 var $id ; 41 var $ref; 42 var $libelle; 43 var $description; 44 var $price; 45 var $tva_tx; 46 var $type; 47 var $seuil_stock_alerte; 48 var $duration_value; 49 var $duration_unit; 50 var $status; 51 52 var $stats_propale=array(); 53 var $stats_commande=array(); 54 var $stats_contrat=array(); 55 var $stats_facture=array(); 56 57 var $typeprodserv; 58 var $error; 59 60 61 /** 62 * \brief Constructeur de la classe 63 * \param DB Handler accès base de données 64 * \param id Id produit (0 par defaut) 65 */ 66 function Product($DB, $id=0) 67 { 68 global $langs; 69 70 $this->db = $DB; 71 $this->id = $id ; 72 $this->envente = 0; // deprecated 73 $this->status = 0; 74 $this->seuil_stock_alerte = 0; 75 76 $this->typeprodser[0]=$langs->trans("Product"); 77 $this->typeprodser[1]=$langs->trans("Service"); 78 } 79 80 81 /** 82 * \brief Vérifie que la référence et libellé du produit est non null 83 * \return int 1 si ok, 0 sinon 84 */ 85 86 function check() 87 { 88 $this->ref = ereg_replace("'","",stripslashes($this->ref)); 89 $this->ref = ereg_replace("\"","",stripslashes($this->ref)); 90 91 $err = 0; 92 if (strlen(trim($this->ref)) == 0) 93 $err++; 94 95 if (strlen(trim($this->libelle)) == 0) 96 $err++; 97 98 if ($err > 0) 99 { 100 return 0; 101 } 102 else 103 { 104 return 1; 105 } 106 } 107 108 109 /** 110 * \brief Insère le produit en base 111 * \param user Utilisateur qui effectue l'insertion 112 */ 113 function create($user) 114 { 115 116 $this->ref = trim(sanitize_string($this->ref)); 117 118 if (strlen($this->tva_tx)==0) $this->tva_tx = 0; 119 if (strlen($this->price)==0) $this->price = 0; 120 if (strlen($this->envente)==0) $this->envente = 0; // deprecated 121 if (strlen($this->status)==0) $this->status = 0; 122 $this->price = ereg_replace(",",".",$this->price); 123 124 dolibarr_syslog("Product::Create ref=".$this->ref." Categorie : ".$this->catid); 125 126 $this->db->begin(); 127 128 $sql = "SELECT count(*)"; 129 $sql .= " FROM ".MAIN_DB_PREFIX."product WHERE ref = '" .$this->ref."'"; 130 131 $result = $this->db->query($sql) ; 132 if ($result) 133 { 134 $row = $this->db->fetch_array($result); 135 if ($row[0] == 0) 136 { 137 // Produit non deja existant 138 $sql = "INSERT INTO ".MAIN_DB_PREFIX."product "; 139 $sql.= " (datec, "; 140 if ($this->ref) $sql.= "ref, "; 141 $sql.= "fk_user_author, fk_product_type, price)"; 142 $sql.= " VALUES (now(), "; 143 if ($this->ref) $sql.= "'".$this->ref."', "; 144 $sql.= $user->id.", ".$this->type.", '" . $this->price . "')"; 145 $result = $this->db->query($sql); 146 if ( $result ) 147 { 148 $id = $this->db->last_insert_id(MAIN_DB_PREFIX."product"); 149 150 if ($id > 0) 151 { 152 $this->id = $id; 153 $this->_log_price($user); 154 if ( $this->update($id, $user) > 0) 155 { 156 if ($this->catid > 0) 157 { 158 $cat = new Categorie ($this->db, $this->catid); 159 $cat->add_product($this); 160 } 161 $this->db->commit(); 162 return $id; 163 } 164 else { 165 $this->db->rollback(); 166 return -5; 167 } 168 } 169 else 170 { 171 $this->db->rollback(); 172 return -4; 173 } 174 } 175 else 176 { 177 $this->error=$this->db->error()." - ".$sql; 178 $this->db->rollback(); 179 return -3; 180 } 181 } 182 else 183 { 184 $this->db->rollback(); 185 return -2; 186 } 187 } 188 189 $this->error=$this->db->error(); 190 $this->db->rollback(); 191 return -1; 192 } 193 194 195 /** 196 * \brief Mise à jour du produit en base 197 * \param id id du produit 198 * \param user utilisateur qui effectue l'insertion 199 * \return int 1 si ok, -1 si ref deja existante, -2 autre erreur 200 */ 201 function update($id, $user) 202 { 203 global $langs; 204 $langs->load("main"); 205 $langs->load("products"); 206 207 if (! $this->libelle) $this->libelle = 'LIBELLE MANQUANT'; 208 209 $this->ref = trim(sanitize_string($this->ref)); 210 $this->libelle = trim($this->libelle); 211 $this->description = trim($this->description); 212 $this->note = trim($this->note); 213 214 $sql = "UPDATE ".MAIN_DB_PREFIX."product "; 215 $sql .= " SET label = '" . addslashes($this->libelle) ."'"; 216 if ($this->ref) $sql .= ",ref = '" . $this->ref ."'"; 217 $sql .= ",tva_tx = " . $this->tva_tx ; 218 $sql .= ",envente = " . $this->envente ; 219 $sql .= ",seuil_stock_alerte = " . $this->seuil_stock_alerte ; 220 $sql .= ",description = '" . addslashes($this->description) ."'"; 221 $sql .= ",note = '" . addslashes($this->note) ."'"; 222 $sql .= ",duration = '" . $this->duration_value . $this->duration_unit ."'"; 223 $sql .= " WHERE rowid = " . $id; 224 225 if ( $this->db->query($sql) ) 226 { 227 return 1; 228 } 229 else 230 { 231 if ($this->db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') 232 { 233 $this->error=$langs->trans("Error")." : ".$langs->trans("ErrorProductAlreadyExists",$this->ref); 234 return -1; 235 } 236 else 237 { 238 $this->error=$langs->trans("Error")." : ".$this->db->error()." - ".$sql; 239 return -2; 240 } 241 } 242 } 243 244 245 /** 246 * \brief Ajoute un changement de prix en base dans l'historique des prix 247 * \param user utilisateur qui modifie le prix 248 */ 249 function _log_price($user) 250 { 251 // On supprimme ligne existante au cas ou 252 $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_price "; 253 $sql .= "WHERE date_price = now()"; 254 $sql .= " and fk_product = ".$this->id; 255 $sql .= " and fk_user_author = ".$user->id; 256 $sql .= " and price = ".ereg_replace(",",".",$this->price); 257 $sql .= " and envente = ".$this->envente; 258 $sql .= " and tva_tx = ".$this->tva_tx; 259 260 $this->db->query($sql); 261 262 // On ajoute nouveau tarif 263 $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_price(date_price,fk_product,fk_user_author,price,envente,tva_tx) "; 264 $sql .= " VALUES(now(),".$this->id.",".$user->id.",".ereg_replace(",",".",$this->price).",".$this->envente.",".$this->tva_tx; 265 $sql .= ")"; 266 if ($this->db->query($sql) ) 267 { 268 return 1; 269 } 270 else 271 { 272 dolibarr_print_error($this->db); 273 return 0; 274 } 275 } 276 277 278 /** 279 * \brief Lit le prix pratiqué par un fournisseur 280 * \param fourn_id Id du fournisseur 281 * \param qty Quantite pour lequel le prix est valide 282 * \return int <0 si ko, 0 si ok mais rien trouvé, 1 si ok et trouvé 283 */ 284 function get_buyprice($fourn_id, $qty) 285 { 286 $result = 0; 287 $sql = "SELECT pf.price as price, pf.quantity as quantity"; 288 $sql.= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price as pf"; 289 $sql.= " WHERE pf.fk_soc = ".$fourn_id; 290 $sql.= " AND pf.fk_product =" .$this->id; 291 $sql.= " AND quantity <= ".$qty; 292 $sql.= " ORDER BY quantity DESC"; 293 $sql.= " LIMIT 1"; 294 295 dolibarr_syslog("Product::get_buyprice $fourn_id,$qty sql=$sql"); 296 297 $resql = $this->db->query($sql); 298 if ($resql) 299 { 300 $obj = $this->db->fetch_object($resql); 301 if ($obj && $obj->quantity > 0) 302 { 303 $this->buyprice = $obj->price; // \deprecated 304 $this->fourn_pu = $obj->price / $obj->quantity; // Prix unitaire du produit pour le fournisseur $fourn_id 305 return 1; 306 } 307 else 308 { 309 return 0; 310 } 311 } 312 else 313 { 314 return -1; 315 } 316 return $result; 317 } 318 319 320 /** 321 * \brief Modifie le prix d'achat pour un fournisseur 322 * \param id_fourn Id du fournisseur 323 * \param qty Quantite pour lequel le prix est valide 324 * \param buyprice Prix d'achat pour la quantité 325 * \param user Objet user de l'utilisateur qui modifie 326 */ 327 function update_buyprice($id_fourn, $qty, $buyprice, $user) 328 { 329 $error=0; 330 $this->db->begin(); 331 332 // Supprime prix courant du fournisseur pour cette quantité 333 $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_fournisseur_price "; 334 $sql .= " WHERE "; 335 $sql .= " fk_product = ".$this->id; 336 $sql .= " AND fk_soc = ".$id_fourn; 337 $sql .= " AND quantity = ".$qty; 338 339 if ($this->db->query($sql)) 340 { 341 // Ajoute prix courant du fournisseur pour cette quantité 342 $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_fournisseur_price "; 343 $sql .= " SET datec = now()"; 344 $sql .= " ,fk_product = ".$this->id; 345 $sql .= " ,fk_soc = ".$id_fourn; 346 $sql .= " ,fk_user = ".$user->id; 347 $sql .= " ,price = ".ereg_replace(",",".",$buyprice); 348 $sql .= " ,quantity = ".$qty; 349 350 if (! $this->db->query($sql)) 351 { 352 $error++; 353 } 354 355 if (! $error) { 356 // Ajoute modif dans table log 357 $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_fournisseur_price_log "; 358 $sql .= " SET datec = now()"; 359 $sql .= " ,fk_product = ".$this->id; 360 $sql .= " ,fk_soc = ".$id_fourn; 361 $sql .= " ,fk_user = ".$user->id; 362 $sql .= " ,price = ".ereg_replace(",",".",$buyprice); 363 $sql .= " ,quantity = ".$qty; 364 365 if (! $this->db->query($sql)) 366 { 367 $error++; 368 } 369 } 370 371 if (! $error) 372 { 373 $this->db->commit(); 374 return 0; 375 } 376 else 377 { 378 $this->error=$this->db->error()." ($sql)"; 379 $this->db->rollback(); 380 return -2; 381 } 382 } 383 else 384 { 385 $this->error=$this->db->error()." ($sql)"; 386 $this->db->rollback(); 387 return -1; 388 } 389 } 390 391 392 /** 393 * \brief Modifie le prix d'un produit/service 394 * \param id id du produit/service à modifier 395 * \param user utilisateur qui modifie le prix 396 */ 397 function update_price($id, $user) 398 { 399 if (strlen(trim($this->price)) > 0 ) 400 { 401 $sql = "UPDATE ".MAIN_DB_PREFIX."product "; 402 $sql .= " SET price = " . ereg_replace(",",".",$this->price); 403 $sql .= " WHERE rowid = " . $id; 404 405 if ( $this->db->query($sql) ) 406 { 407 $this->_log_price($user); 408 return 1; 409 } 410 else 411 { 412 dolibarr_print_error($this->db); 413 return -1; 414 } 415 } 416 else 417 { 418 $this->error = "Prix saisi invalide."; 419 return -2; 420 } 421 } 422 423 424 /** 425 * \brief Charge le produit/service en mémoire 426 * \param id Id du produit/service à charger 427 * \param ref Ref du produit/service à charger 428 * \return int <0 si ko, >0 si ok 429 */ 430 function fetch($id='',$ref='') 431 { 432 global $langs; 433 434 // Verification parametres 435 if (! $id && ! $ref) 436 { 437 $this->error=$langs->trans('ErrorWrongParameters'); 438 return -1; 439 } 440 441 $sql = "SELECT rowid, ref, label, description, note, price, tva_tx, envente,"; 442 $sql.= " nbvente, fk_product_type, duration, seuil_stock_alerte"; 443 $sql.= " FROM ".MAIN_DB_PREFIX."product"; 444 if ($id) $sql.= " WHERE rowid = ".$id; 445 if ($ref) $sql.= " WHERE ref = '".addslashes($ref)."'"; 446 447 $result = $this->db->query($sql) ; 448 if ( $result ) 449 { 450 $result = $this->db->fetch_array(); 451 452 $this->id = $result["rowid"]; 453 $this->ref = $result["ref"]; 454 $this->libelle = stripslashes($result["label"]); 455 $this->description = stripslashes($result["description"]); 456 $this->note = stripslashes($result["note"]); 457 $this->price = $result["price"]; 458 $this->tva_tx = $result["tva_tx"]; 459 $this->type = $result["fk_product_type"]; 460 $this->nbvente = $result["nbvente"]; 461 $this->envente = $result["envente"]; // deprecated 462 $this->status = $result["envente"]; 463 $this->duration = $result["duration"]; 464 $this->duration_value = substr($result["duration"],0,strlen($result["duration"])-1); 465 $this->duration_unit = substr($result["duration"],-1); 466 $this->seuil_stock_alerte = $result["seuil_stock_alerte"]; 467 468 $this->label_url = '<a href="'.DOL_URL_ROOT.'/product/fiche.php?id='.$this->id.'">'.$this->libelle.'</a>'; 469 470 if ($this->type == 0) 471 { 472 $this->isproduct = 1; 473 $this->isservice = 0; 474 } 475 else 476 { 477 $this->isproduct = 0; 478 $this->isservice = 1; 479 } 480 481 $this->db->free(); 482 483 $sql = "SELECT reel, fk_entrepot"; 484 $sql .= " FROM ".MAIN_DB_PREFIX."product_stock WHERE fk_product = ".$this->id; 485 $result = $this->db->query($sql) ; 486 if ($result) 487 { 488 $num = $this->db->num_rows($result); 489 $i=0; 490 if ($num > 0) 491 { 492 while ($i < $num ) 493 { 494 $row = $this->db->fetch_row($result); 495 $this->stock_entrepot[$row[1]] = $row[0]; 496 497 $this->stock_reel = $this->stock_reel + $row[0]; 498 $i++; 499 } 500 501 $this->no_stock = 0; 502 } 503 else 504 { 505 $this->no_stock = 1; 506 } 507 $this->db->free($result); 508 return 1; 509 } 510 else 511 { 512 $this->error=$this->db->error(); 513 return -2; 514 } 515 } 516 else 517 { 518 dolibarr_print_error($this->db); 519 return -1; 520 } 521 } 522 523 524 /** 525 * \brief Charge les propriétés ref_previous et ref_next 526 * \param filter filtre 527 * \return int <0 si ko, >0 si ok 528 */ 529 function load_previous_next_ref($filtre='') 530 { 531 $sql = "SELECT MAX(ref)"; 532 $sql.= " FROM ".MAIN_DB_PREFIX."product"; 533 $sql.= " WHERE ref < '".addslashes($this->ref)."'"; 534 if ($filter) $sql.=" AND ".$filter; 535 $result = $this->db->query($sql) ; 536 if (! $result) 537 { 538 $this->error=$this->db->error(); 539 return -1; 540 } 541 $row = $this->db->fetch_row($result); 542 $this->ref_previous = $row[0]; 543 544 $sql = "SELECT MIN(ref)"; 545 $sql.= " FROM ".MAIN_DB_PREFIX."product"; 546 $sql.= " WHERE ref > '".addslashes($this->ref)."'"; 547 if ($filter) $sql.=" AND ".$filter; 548 $result = $this->db->query($sql) ; 549 if (! $result) 550 { 551 $this->error=$this->db->error(); 552 return -2; 553 } 554 $row = $this->db->fetch_row($result); 555 $this->ref_next = $row[0]; 556 557 return 1; 558 } 559 560 561 /** 562 * \brief Charge tableau des stats propale pour le produit/service 563 * \param socid Id societe 564 * \return array Tableau des stats 565 */ 566 function load_stats_propale($socid=0) 567 { 568 $sql = "SELECT COUNT(DISTINCT pr.fk_soc) as nb_customers, COUNT(DISTINCT pr.rowid) as nb,"; 569 $sql.= " COUNT(pd.rowid) as nb_rows, SUM(pd.qty) as qty"; 570 $sql.= " FROM ".MAIN_DB_PREFIX."propaldet as pd, ".MAIN_DB_PREFIX."product as p, ".MAIN_DB_PREFIX."propal as pr"; 571 $sql.= " WHERE p.rowid = pd.fk_product AND pd.fk_propal = pr.rowid AND p.rowid = ".$this->id; 572 //$sql.= " AND pr.fk_statut != 0"; 573 if ($socid > 0) 574 { 575 $sql .= " AND pr.fk_soc = $socid"; 576 } 577 578 $result = $this->db->query($sql) ; 579 if ( $result ) 580 { 581 $obj=$this->db->fetch_object($result); 582 $this->stats_propale['customers']=$obj->nb_customers; 583 $this->stats_propale['nb']=$obj->nb; 584 $this->stats_propale['rows']=$obj->nb_rows; 585 $this->stats_propale['qty']=$obj->qty?$obj->qty:0; 586 return 1; 587 } 588 else 589 { 590 $this->error=$this->db->error(); 591 return -1; 592 } 593 } 594 595 596 /** 597 * \brief Charge tableau des stats commande pour le produit/service 598 * \param socid Id societe 599 * \return array Tableau des stats 600 */ 601 function load_stats_commande($socid=0) 602 { 603 $sql = "SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,"; 604 $sql.= " COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty"; 605 $sql.= " FROM ".MAIN_DB_PREFIX."commandedet as cd, ".MAIN_DB_PREFIX."product as p,"; 606 $sql.= " ".MAIN_DB_PREFIX."commande as c"; 607 $sql.= " WHERE c.rowid = cd.fk_commande AND p.rowid = cd.fk_product AND p.rowid = ".$this->id; 608 //$sql.= " AND c.fk_statut != 0"; 609 if ($socid > 0) 610 { 611 $sql .= " AND c.fk_soc = $socid"; 612 } 613 614 $result = $this->db->query($sql) ; 615 if ( $result ) 616 { 617 $obj=$this->db->fetch_object($result); 618 $this->stats_commande['customers']=$obj->nb_customers; 619 $this->stats_commande['nb']=$obj->nb; 620 $this->stats_commande['rows']=$obj->nb_rows; 621 $this->stats_commande['qty']=$obj->qty?$obj->qty:0; 622 return 1; 623 } 624 else 625 { 626 $this->error=$this->db->error(); 627 return -1; 628 } 629 } 630 631 /** 632 * \brief Charge tableau des stats contrat pour le produit/service 633 * \param socid Id societe 634 * \return array Tableau des stats 635 */ 636 function load_stats_contrat($socid=0) 637 { 638 $sql = "SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,"; 639 $sql.= " COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty"; 640 $sql.= " FROM ".MAIN_DB_PREFIX."contratdet as cd, ".MAIN_DB_PREFIX."product as p,"; 641 $sql.= " ".MAIN_DB_PREFIX."contrat as c"; 642 $sql.= " WHERE c.rowid = cd.fk_contrat AND p.rowid = cd.fk_product AND p.rowid = ".$this->id; 643 //$sql.= " AND c.statut != 0"; 644 if ($socid > 0) 645 { 646 $sql .= " AND c.fk_soc = $socid"; 647 } 648 649 $result = $this->db->query($sql) ; 650 if ( $result ) 651 { 652 $obj=$this->db->fetch_object($result); 653 $this->stats_contrat['customers']=$obj->nb_customers; 654 $this->stats_contrat['nb']=$obj->nb; 655 $this->stats_contrat['rows']=$obj->nb_rows; 656 $this->stats_contrat['qty']=$obj->qty?$obj->qty:0; 657 return 1; 658 } 659 else 660 { 661 $this->error=$this->db->error(); 662 return -1; 663 } 664 } 665 666 /** 667 * \brief Charge tableau des stats facture pour le produit/service 668 * \param socid Id societe 669 * \return array Tableau des stats 670 */ 671 function load_stats_facture($socid=0) 672 { 673 $sql = "SELECT COUNT(DISTINCT f.fk_soc) as nb_customers, COUNT(DISTINCT f.rowid) as nb,"; 674 $sql.= " COUNT(pd.rowid) as nb_rows, SUM(pd.qty) as qty"; 675 $sql.= " FROM ".MAIN_DB_PREFIX."facturedet as pd, ".MAIN_DB_PREFIX."product as p"; 676 $sql.= ", ".MAIN_DB_PREFIX."facture as f"; 677 $sql.= " WHERE f.rowid = pd.fk_facture AND p.rowid = pd.fk_product AND p.rowid = ".$this->id; 678 //$sql.= " AND f.fk_statut != 0"; 679 if ($socid > 0) 680 { 681 $sql .= " AND f.fk_soc = $socid"; 682 } 683 684 $result = $this->db->query($sql) ; 685 if ( $result ) 686 { 687 $obj=$this->db->fetch_object($result); 688 $this->stats_facture['customers']=$obj->nb_customers; 689 $this->stats_facture['nb']=$obj->nb; 690 $this->stats_facture['rows']=$obj->nb_rows; 691 $this->stats_facture['qty']=$obj->qty?$obj->qty:0; 692 return 1; 693 } 694 else 695 { 696 $this->error=$this->db->error(); 697 return -1; 698 } 699 } 700 701 702 /** 703 * \brief Renvoie tableau des stats pour une requete donnée 704 * \param sql Requete a exécuter 705 * \return array Tableau de stats 706 */ 707 function _get_stats($sql) 708 { 709 $result = $this->db->query($sql) ; 710 if ($result) 711 { 712 $num = $this->db->num_rows($result); 713 $i = 0; 714 while ($i < $num) 715 { 716 $arr = $this->db->fetch_array($result); 717 $tab[$arr[1]] = $arr[0]; 718 $i++; 719 } 720 } 721 722 $year = strftime('%Y',time()); 723 $month = strftime('%m',time()); 724 $result = array(); 725 726 for ($j = 0 ; $j < 12 ; $j++) 727 { 728 $idx=ucfirst(substr( strftime("%b",mktime(12,0,0,$month,1,$year)) ,0,3) ); 729 $monthnum=sprintf("%02s",$month); 730 731 $result[$j] = array($idx,isset($tab[$year.$month])?$tab[$year.$month]:0); 732 // $result[$j] = array($monthnum,isset($tab[$year.$month])?$tab[$year.$month]:0); 733 734 $month = "0".($month - 1); 735 if (strlen($month) == 3) 736 { 737 $month = substr($month,1); 738 } 739 if ($month == 0) 740 { 741 $month = 12; 742 $year = $year - 1; 743 } 744 } 745 return array_reverse($result); 746 747 } 748 749 750 /** 751 * \brief Renvoie le nombre de ventes du produit/service par mois 752 * \param socid id societe 753 * \return array nombre de vente par mois 754 */ 755 756 function get_nb_vente($socid=0) 757 { 758 $sql = "SELECT sum(d.qty), date_format(f.datef, '%Y%m') "; 759 $sql .= " FROM ".MAIN_DB_PREFIX."facturedet as d, ".MAIN_DB_PREFIX."facture as f"; 760 $sql .= " WHERE f.rowid = d.fk_facture and d.fk_product =".$this->id; 761 if ($socid > 0) 762 { 763 $sql .= " AND f.fk_soc = $socid"; 764 } 765 $sql .= " GROUP BY date_format(f.datef,'%Y%m') DESC ;"; 766 767 return $this->_get_stats($sql); 768 } 769 770 771 /** 772 * \brief Renvoie le nombre de factures dans lesquelles figure le produit par mois 773 * \param socid id societe 774 * \return array nombre de factures par mois 775 */ 776 777 function get_num_vente($socid=0) 778 { 779 $sql = "SELECT count(*), date_format(f.datef, '%Y%m') "; 780 $sql .= " FROM ".MAIN_DB_PREFIX."facturedet as d, ".MAIN_DB_PREFIX."facture as f"; 781 $sql .= " WHERE f.rowid = d.fk_facture AND d.fk_product =".$this->id; 782 if ($socid > 0) 783 { 784 $sql .= " AND f.fk_soc = $socid"; 785 } 786 $sql .= " GROUP BY date_format(f.datef,'%Y%m') DESC ;"; 787 788 return $this->_get_stats($sql); 789 } 790 791 792 /** 793 * \brief Renvoie le nombre de propales dans lesquelles figure le produit par mois 794 * \param socid id societe 795 * \return array nombre de propales par mois 796 */ 797 798 function get_num_propal($socid=0) 799 { 800 $sql = "SELECT count(*), date_format(p.datep, '%Y%m') "; 801 $sql .= " FROM ".MAIN_DB_PREFIX."propaldet as d, ".MAIN_DB_PREFIX."propal as p"; 802 $sql .= " WHERE p.rowid = d.fk_propal and d.fk_product =".$this->id; 803 if ($socid > 0) 804 { 805 $sql .= " AND p.fk_soc = $socid"; 806 } 807 $sql .= " GROUP BY date_format(p.datep,'%Y%m') DESC ;"; 808 809 return $this->_get_stats($sql); 810 } 811 812 813 /** 814 * \brief Lie un fournisseur au produit/service 815 * \param user Utilisateur qui fait le lien 816 * \param id_fourn Id du fournisseur 817 * \param ref_fourn Reference chez le fournisseur 818 * \return int < 0 si erreur, > 0 si ok 819 */ 820 821 function add_fournisseur($user, $id_fourn, $ref_fourn) 822 { 823 $sql = "SELECT count(*) as nb"; 824 $sql.= " FROM ".MAIN_DB_PREFIX."product_fournisseur"; 825 $sql.= " WHERE fk_product = ".$this->id." AND fk_soc = ".$id_fourn; 826 $sql.= " AND ref_fourn = '".$ref_fourn."'"; 827 828 $resql=$this->db->query($sql); 829 if ($resql) 830 { 831 $obj = $this->db->fetch_object($resql); 832 if ($obj->nb == 0) 833 { 834 $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_fournisseur "; 835 $sql .= " (datec, fk_product, fk_soc, ref_fourn, fk_user_author)"; 836 $sql .= " VALUES (now(), $this->id, $id_fourn, '$ref_fourn', $user->id)"; 837 838 if ($this->db->query($sql)) 839 { 840 return 1; 841 } 842 else 843 { 844 $this->error=$this->db->error(); 845 return -1; 846 } 847 } 848 $this->db->free($resql); 849 } 850 else 851 { 852 $this->error=$this->db->error(); 853 return -2; 854 } 855 } 856 857 858 /** 859 * \brief Renvoie le nombre de fournisseurs 860 * \return int nombre de fournisseur 861 */ 862 863 function count_fournisseur() 864 { 865 $sql = "SELECT fk_soc"; 866 $sql .= " FROM ".MAIN_DB_PREFIX."product_fournisseur as p"; 867 $sql .= " WHERE p.fk_product = ".$this->id; 868 869 $result = $this->db->query($sql) ; 870 871 if ( $result ) 872 { 873 $num = $this->db->num_rows(); 874 875 if ($num == 1) 876 { 877 $row = $this->db->fetch_row(); 878 $this->fourn_appro_open = $row[0]; 879 return 1; 880 } 881 else 882 { 883 return 0; 884 } 885 } 886 else 887 { 888 return 0; 889 } 890 } 891 892 893 /** 894 * 895 * 896 */ 897 function fastappro($user) 898 { 899 include_once DOL_DOCUMENT_ROOT."/fourn/fournisseur.class.php"; 900 901 $nbf = $this->count_fournisseur(); 902 if ($nbf == 1) 903 { 904 dolibarr_syslog("Product::fastappro"); 905 $fournisseur = new Fournisseur($this->db); 906 $fournisseur->fetch($this->fourn_appro_open); 907 908 $fournisseur->ProductCommande($user, $this->id); 909 } 910 911 } 912 913 914 /** 915 * \brief Supprime un tarif fournisseur 916 * \param user utilisateur qui défait le lien 917 * \param id_fourn id du fournisseur 918 * \param qty quantit 919 * \return int < 0 si erreur, > 0 si ok 920 */ 921 function remove_price($user, $id_fourn, $qty) 922 { 923 $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_fournisseur_price"; 924 $sql.= " WHERE fk_product = $this->id AND fk_soc = $id_fourn and quantity = '".$qty."';"; 925 926 if ($this->db->query($sql) ) 927 { 928 return 1; 929 } 930 else 931 { 932 dolibarr_print_error($this->db); 933 return -1; 934 } 935 } 936 937 /** 938 * \brief Délie un fournisseur au produit/service 939 * \param user utilisateur qui défait le lien 940 * \param id_fourn id du fournisseur 941 * \return int < 0 si erreur, > 0 si ok 942 */ 943 function remove_fournisseur($user, $id_fourn) 944 { 945 $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_fournisseur "; 946 $sql.= " WHERE fk_product = $this->id AND fk_soc = $id_fourn;"; 947 948 if ($this->db->query($sql) ) 949 { 950 return 1; 951 } 952 else 953 { 954 dolibarr_print_error($this->db); 955 return -1; 956 } 957 } 958 959 /** 960 * \brief Recopie les prix d'un produit/service sur un autre 961 * \param fromId Id produit source 962 * \param toId Id produit cible 963 * \return int < 0 si erreur, > 0 si ok 964 */ 965 function clone_price($fromId, $toId) 966 { 967 global $db; 968 969 $db->begin(); 970 971 // les prix 972 $sql = "insert " .MAIN_DB_PREFIX."product_price (" 973 . " fk_product, date_price, price, tva_tx, fk_user_author, envente )" 974 . " select ".$toId . ", date_price, price, tva_tx, fk_user_author, envente " 975 . " from ".MAIN_DB_PREFIX."product_price " 976 . " where fk_product = ". $fromId . ";" ; 977 if ( ! $db->query($sql ) ) { 978 $db->rollback(); 979 return -1; 980 } 981 $db->commit(); 982 return 1; 983 } 984 985 /** 986 * \brief Recopie les fournisseurs et prix fournisseurs d'un produit/service sur un autre 987 * \param fromId Id produit source 988 * \param toId Id produit cible 989 * \return int < 0 si erreur, > 0 si ok 990 */ 991 function clone_fournisseurs($fromId, $toId) 992 { 993 global $db; 994 995 $db->begin(); 996 997 // les fournisseurs 998 $sql = "insert ".MAIN_DB_PREFIX."product_fournisseur (" 999 . " datec, fk_product, fk_soc, ref_fourn, fk_user_author )" 1000 . " select now(), ".$toId.", fk_soc, ref_fourn, fk_user_author" 1001 . " from ".MAIN_DB_PREFIX."product_fournisseur " 1002 . " where fk_product = ".$fromId .";" ; 1003 if ( ! $db->query($sql ) ) { 1004 $db->rollback(); 1005 return -1; 1006 } 1007 // les prix de fournisseurs. 1008 $sql = "insert ".MAIN_DB_PREFIX."product_fournisseur_price (" 1009 . " datec, fk_product, fk_soc, price, quantity, fk_user )" 1010 . " select now(), ".$toId. ", fk_soc, price, quantity, fk_user" 1011 . " from ".MAIN_DB_PREFIX."product_fournisseur_price" 1012 . " where fk_product = ".$fromId.";"; 1013 if ( ! $db->query($sql ) ) { 1014 $db->rollback(); 1015 return -1; 1016 } 1017 $db->commit(); 1018 return 1; 1019 } 1020 1021 /** 1022 * \brief Retourne le libellé du statut d'une facture (brouillon, validée, abandonnée, payée) 1023 * \param mode 0=libellé long, 1=libellé court 1024 * \return string Libelle 1025 */ 1026 function getLibStatut($mode=0) 1027 { 1028 return $this->LibStatut($this->status,$mode); 1029 } 1030 1031 /** 1032 * \brief Renvoi le libellé d'un statut donne 1033 * \param status Statut 1034 * \param mode 0=libellé long, 1=libellé court 1035 * \return string Libellé du statut 1036 */ 1037 function LibStatut($status,$mode=0) 1038 { 1039 global $langs; 1040 $langs->load('products'); 1041 if ($status == 0) return $langs->trans('ProductStatusNotOnSell'.($mode?'Short':'')); 1042 if ($status == 1) return $langs->trans('ProductStatusOnSell'.($mode?'Short':'')); 1043 return $langs->trans('Unknown'); 1044 } 1045 1046 /** 1047 * \brief Entre un nombre de piece du produit en stock dans un entrepôt 1048 * \param id_entrepot id de l'entrepot 1049 * \param nbpiece nombre de pieces 1050 */ 1051 function create_stock($id_entrepot, $nbpiece) 1052 { 1053 1054 $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_stock "; 1055 $sql .= " (fk_product, fk_entrepot, reel)"; 1056 $sql .= " VALUES ($this->id, $id_entrepot, $nbpiece)"; 1057 1058 if ($this->db->query($sql) ) 1059 { 1060 return 1; 1061 } 1062 else 1063 { 1064 dolibarr_print_error($this->db); 1065 return -1; 1066 } 1067 } 1068 1069 1070 /** 1071 * \brief Ajuste le stock d'un entrepôt pour le produit à une valeure donnée 1072 * \param user utilisateur qui demande l'ajustement 1073 * \param id_entrepot id de l'entrepot 1074 * \param nbpiece nombre de pieces 1075 * \param mouvement 0 = ajout, 1 = suppression 1076 */ 1077 function correct_stock($user, $id_entrepot, $nbpiece, $mouvement) 1078 { 1079 1080 $sql = "SELECT count(*) FROM ".MAIN_DB_PREFIX."product_stock "; 1081 $sql .= " WHERE fk_product = $this->id AND fk_entrepot = $id_entrepot"; 1082 1083 if ($this->db->query($sql) ) 1084 { 1085 $row = $this->db->fetch_row(0); 1086 if ($row[0] > 0) 1087 { 1088 return $this->ajust_stock($user, $id_entrepot, $nbpiece, $mouvement); 1089 } 1090 else 1091 { 1092 return $this->create_stock($id_entrepot, $nbpiece); 1093 } 1094 } 1095 else 1096 { 1097 dolibarr_print_error($this->db); 1098 $this->db->rollback(); 1099 return -1; 1100 } 1101 } 1102 1103 1104 /** 1105 * \brief Augment ou réduit la valeur de stock pour le produit 1106 * \param user utilisateur qui demande l'ajustement 1107 * \param id_entrepot id de l'entrepot 1108 * \param nbpiece nombre de pieces 1109 * \param mouvement 0 = ajout, 1 = suppression 1110 */ 1111 1112 function ajust_stock($user, $id_entrepot, $nbpiece, $mouvement) 1113 { 1114 $op[0] = "+" . trim($nbpiece); 1115 $op[1] = "-" . trim($nbpiece); 1116 1117 if ($this->db->begin()) 1118 { 1119 1120 $sql = "UPDATE ".MAIN_DB_PREFIX."product "; 1121 $sql .= " SET stock_commande = stock_commande ".$op[$mouvement].", stock_propale = stock_propale ".$op[$mouvement]; 1122 $sql .= " WHERE rowid = $this->id "; 1123 1124 if ($this->db->query($sql) ) 1125 { 1126 $sql = "UPDATE ".MAIN_DB_PREFIX."product_stock "; 1127 $sql .= " SET reel = reel ".$op[$mouvement]; 1128 $sql .= " WHERE fk_product = $this->id AND fk_entrepot = $id_entrepot"; 1129 1130 if ($this->db->query($sql) ) 1131 { 1132 $sql = "INSERT INTO ".MAIN_DB_PREFIX."stock_mouvement (datem, fk_product, fk_entrepot, value, type_mouvement, fk_user_author)"; 1133 $sql .= " VALUES (now(), $this->id, $id_entrepot, ".$op[$mouvement].", 0, $user->id)"; 1134 1135 if ($this->db->query($sql) ) 1136 { 1137 $this->db->commit(); 1138 return 1; 1139 } 1140 else 1141 { 1142 dolibarr_print_error($this->db); 1143 $this->db->rollback(); 1144 return -2; 1145 } 1146 } 1147 else 1148 { 1149 dolibarr_print_error($this->db); 1150 $this->db->rollback(); 1151 return -1; 1152 } 1153 } 1154 else 1155 { 1156 dolibarr_print_error($this->db); 1157 $this->db->rollback(); 1158 return -3; 1159 } 1160 } 1161 } 1162 1163 1164 /** 1165 * \brief Charge les informations relatives à un fournisseur 1166 * \param fournid id du fournisseur 1167 * \return int < 0 si erreur, > 0 si ok 1168 */ 1169 function fetch_fourn_data($fournid) 1170 { 1171 $sql = "SELECT rowid, ref_fourn"; 1172 $sql.= " FROM ".MAIN_DB_PREFIX."product_fournisseur "; 1173 $sql.= " WHERE fk_product = ".$this->id; 1174 $sql.= " AND fk_soc = ".$fournid; 1175 $result = $this->db->query($sql) ; 1176 1177 if ($result) 1178 { 1179 $result = $this->db->fetch_array(); 1180 $this->ref_fourn = $result["ref_fourn"]; 1181 return 1; 1182 } 1183 else { 1184 return -1; 1185 } 1186 } 1187 1188 1189 /** 1190 * \brief Déplace fichier uploadé sous le nom $files dans le répertoire sdir 1191 * \param sdir Répertoire destination finale 1192 * \param $files Nom du fichier uploadé 1193 */ 1194 function add_photo($sdir, $files) 1195 { 1196 $dir = $sdir .'/'. get_exdir($this->id) . $this->id ."/"; 1197 $dir .= "photos/"; 1198 1199 if (! file_exists($dir)) 1200 { 1201 dolibarr_syslog("Product Create $dir"); 1202 create_exdir($dir); 1203 } 1204 1205 if (file_exists($dir)) 1206 { 1207 // Crée fichier en taille vignette 1208 // \todo A faire 1209 1210 // Crée fichier en taille origine 1211 doliMoveFileUpload($files['tmp_name'], $dir . $files['name']); 1212 } 1213 } 1214 1215 1216 /** 1217 * \brief Affiche la première photo du produit 1218 * \param sdir Répertoire à scanner 1219 * \return boolean true si photo dispo, flase sinon 1220 */ 1221 function is_photo_available($sdir) 1222 { 1223 $pdir = get_exdir($this->id) . $this->id ."/photos/"; 1224 $dir = $sdir . '/'. $pdir; 1225 1226 $nbphoto=0; 1227 if (file_exists($dir)) 1228 { 1229 $handle=opendir($dir); 1230 1231 while (($file = readdir($handle)) != false) 1232 { 1233 if (is_file($dir.$file)) return true; 1234 } 1235 } 1236 return false; 1237 } 1238 1239 1240 /** 1241 * \brief Affiche la première photo du produit 1242 * \param sdir Répertoire à scanner 1243 * \param size 0=taille origine, 1 taille vignette 1244 * \return int Nombre de photos affichées 1245 */ 1246 function show_photo($sdir,$size=0) 1247 { 1248 return $this->show_photos($sdir,$size,1,0); 1249 } 1250 1251 1252 /** 1253 * \brief Affiche toutes les photos du produit (nbmax maximum) 1254 * \param sdir Répertoire à scanner 1255 * \param size 0=taille origine, 1 taille vignette 1256 * \param nbmax Nombre maximum de photos (0=pas de max) 1257 * \param nbbyrow Nombre vignettes par ligne (si mode vignette) 1258 * \return int Nombre de photos affichées 1259 * \todo A virer, seule la methode avec size=0 sert encore. 1260 */ 1261 function show_photos($sdir,$size=0,$nbmax=0,$nbbyrow=5) 1262 { 1263 $pdir = get_exdir($this->id) . $this->id ."/photos/"; 1264 $dir = $sdir . '/'. $pdir; 1265 1266 $nbphoto=0; 1267 if (file_exists($dir)) 1268 { 1269 $handle=opendir($dir); 1270 1271 while (($file = readdir($handle)) != false) 1272 { 1273 $photo=''; 1274 if (is_file($dir.$file)) $photo = $file; 1275 1276 if ($photo) 1277 { 1278 $nbphoto++; 1279 1280 if ($size == 1) { // Format vignette 1281 1282 // On determine nom du fichier vignette 1283 $photo_vignette=''; 1284 if (eregi('(\.jpg|\.bmp|\.gif|\.png|\.tiff)$',$photo,$regs)) { 1285 $photo_vignette=eregi_replace($regs[0],'',$photo)."_small".$regs[0]; 1286 } 1287 1288 1289 if ($nbbyrow && $nbphoto == 1) print '<table width="100%" valign="top" align="center" border="0" cellpadding="2" cellspacing="2">'; 1290 1291 if ($nbbyrow && ($nbphoto % $nbbyrow == 1)) print '<tr align=center valign=middle border=1>'; 1292 if ($nbbyrow) print '<td width="'.ceil(100/$nbbyrow).'%" class="photo">'; 1293 1294 print '<a href="'.DOL_URL_ROOT.'/viewimage.php?modulepart=product&file='.urlencode($pdir.$photo).'" alt="Taille origine" target="_blank">'; 1295 1296 // Si fichier vignette disponible, on l'utilise, sinon on utilise photo origine 1297 if ($photo_vignette && is_file($photo_vignette)) { 1298 print '<img border="0" height="120" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart=product&file='.urlencode($pdir.$photo_vignette).'">'; 1299 } 1300 else { 1301 print '<img border="0" height="120" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart=product&file='.urlencode($pdir.$photo).'">'; 1302 } 1303 1304 print '</a>'; 1305 1306 if ($nbbyrow) print '</td>'; 1307 if ($nbbyrow && ($nbphoto % $nbbyrow == 0)) print '</tr>'; 1308 1309 } 1310 1311 if ($size == 0) // Format origine 1312 print '<img border="0" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart=product&file='.urlencode($pdir.$photo).'">'; 1313 1314 // On continue ou on arrete de boucler ? 1315 if ($nbmax && $nbphoto >= $nbmax) break; 1316 } 1317 } 1318 1319 if ($nbbyrow && $size==1) 1320 { 1321 // Ferme tableau 1322 while ($nbphoto % $nbbyrow) { 1323 print '<td width="'.ceil(100/$nbbyrow).'%"> </td>'; 1324 $nbphoto++; 1325 } 1326 1327 if ($nbphoto) print '</table>'; 1328 } 1329 1330 closedir($handle); 1331 } 1332 1333 return $nbphoto; 1334 } 1335 1336 /** 1337 * \brief Retourne tableau de toutes les photos du produit 1338 * \param dir Répertoire à scanner 1339 * \param nbmax Nombre maximum de photos (0=pas de max) 1340 * \return array Tableau de photos 1341 */ 1342 function liste_photos($dir,$nbmax=0) 1343 { 1344 $nbphoto=0; 1345 $tabobj=array(); 1346 1347 if (file_exists($dir)) 1348 { 1349 $handle=opendir($dir); 1350 1351 while (($file = readdir($handle)) != false) 1352 { 1353 if (is_file($dir.$file)) 1354 { 1355 $nbphoto++; 1356 $photo = $file; 1357 1358 // On determine nom du fichier vignette 1359 $photo_vignette=''; 1360 if (eregi('(\.jpg|\.bmp|\.gif|\.png|\.tiff)$',$photo,$regs)) { 1361 $photo_vignette=eregi_replace($regs[0],'',$photo)."_small".$regs[0]; 1362 } 1363 1364 // Objet 1365 $obj->photo=$photo; 1366 if ($photo_vignette && is_file($photo_vignette)) $obj->photo_vignette=$photo_vignette; 1367 else $obj->photo_vignette=""; 1368 $tabobj[$nbphoto-1]=$obj; 1369 1370 // On continue ou on arrete de boucler ? 1371 if ($nbmax && $nbphoto >= $nbmax) break; 1372 } 1373 } 1374 1375 closedir($handle); 1376 } 1377 1378 return $tabobj; 1379 } 1380 1381 1382 /** 1383 * \brief Charge indicateurs this->nb de tableau de bord 1384 * \return int <0 si ko, >0 si ok 1385 */ 1386 function load_state_board() 1387 { 1388 global $conf; 1389 1390 $this->nb=array(); 1391 1392 $sql = "SELECT count(p.rowid) as nb"; 1393 $sql.= " FROM ".MAIN_DB_PREFIX."product as p"; 1394 $sql.= " WHERE p.fk_product_type = 0"; 1395 $resql=$this->db->query($sql); 1396 if ($resql) 1397 { 1398 while ($obj=$this->db->fetch_object($resql)) 1399 { 1400 $this->nb["products"]=$obj->nb; 1401 } 1402 return 1; 1403 } 1404 else 1405 { 1406 dolibarr_print_error($this->db); 1407 $this->error=$this->db->error(); 1408 return -1; 1409 } 1410 1411 } 1412 1413 } 1414 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Mon Nov 26 12:29:37 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |