38 require_once DOL_DOCUMENT_ROOT.
'/core/lib/product.lib.php';
39 require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobject.class.php';
40 require_once DOL_DOCUMENT_ROOT.
'/product/class/productbatch.class.php';
41 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/entrepot.class.php';
51 public $element =
'product';
56 public $table_element =
'product';
61 public $fk_element =
'fk_product';
66 protected $childtables = array(
67 'supplier_proposaldet',
73 'commande_fournisseurdet'
81 public $ismultientitymanaged = 1;
86 public $picto =
'product';
93 public $regeximgext =
'\.gif|\.jpg|\.jpeg|\.png|\.bmp|\.webp|\.xpm|\.xbm';
127 public $type = self::TYPE_PRODUCT;
155 public $price_min_ttc;
161 public $price_base_type;
165 public $multiprices_ttc = array();
166 public $multiprices_base_type = array();
167 public $multiprices_min = array();
168 public $multiprices_min_ttc = array();
169 public $multiprices_tva_tx = array();
170 public $multiprices_recuperableonly = array();
174 public $prices_by_qty = array();
175 public $prices_by_qty_id = array();
176 public $prices_by_qty_list = array();
189 public $localtax2_tx;
190 public $localtax1_type;
191 public $localtax2_type;
198 public $stock_reel = 0;
205 public $stock_theorique;
222 public $seuil_stock_alerte = 0;
232 public $duration_value;
251 public $status_buy = 0;
265 public $status_batch = 0;
283 public $weight_units;
285 public $length_units;
289 public $height_units;
291 public $surface_units;
293 public $volume_units;
296 public $net_measure_units;
298 public $accountancy_code_sell;
299 public $accountancy_code_sell_intra;
300 public $accountancy_code_sell_export;
301 public $accountancy_code_buy;
302 public $accountancy_code_buy_intra;
303 public $accountancy_code_buy_export;
317 public $barcode_type;
324 public $barcode_type_code;
331 public $barcodes_extra = array();
333 public $stats_propale = array();
334 public $stats_commande = array();
335 public $stats_contrat = array();
336 public $stats_facture = array();
337 public $stats_commande_fournisseur = array();
338 public $stats_reception = array();
339 public $stats_mrptoconsume = array();
340 public $stats_mrptoproduce = array();
342 public $multilangs = array();
351 public $date_creation;
356 public $date_modification;
371 public $fk_default_warehouse;
375 public $fk_price_expression;
379 public $fourn_price_base_type;
387 public $ref_supplier;
401 public $price_autogen = 0;
408 public $supplierprices;
413 public $fields = array(
414 'rowid' => array(
'type'=>
'integer',
'label'=>
'TechnicalID',
'enabled'=>1,
'visible'=>-2,
'notnull'=>1,
'index'=>1,
'position'=>1,
'comment'=>
'Id'),
415 'ref' =>array(
'type'=>
'varchar(128)',
'label'=>
'Ref',
'enabled'=>1,
'visible'=>1,
'notnull'=>1,
'showoncombobox'=>1,
'index'=>1,
'position'=>10,
'searchall'=>1,
'comment'=>
'Reference of object'),
416 'barcode' =>array(
'type'=>
'varchar(255)',
'label'=>
'Barcode',
'enabled'=>
'!empty($conf->barcode->enabled)',
'visible'=>-1,
'showoncombobox'=>1),
417 'entity' =>array(
'type'=>
'integer',
'label'=>
'Entity',
'enabled'=>1,
'visible'=>0,
'default'=>1,
'notnull'=>1,
'index'=>1,
'position'=>20),
418 'label' =>array(
'type'=>
'varchar(255)',
'label'=>
'Label',
'enabled'=>1,
'visible'=>1,
'notnull'=>1,
'showoncombobox'=>1),
419 'note_public' =>array(
'type'=>
'html',
'label'=>
'NotePublic',
'enabled'=>1,
'visible'=>0,
'position'=>61),
420 'note' =>array(
'type'=>
'html',
'label'=>
'NotePrivate',
'enabled'=>1,
'visible'=>0,
'position'=>62),
421 'datec' =>array(
'type'=>
'datetime',
'label'=>
'DateCreation',
'enabled'=>1,
'visible'=>-2,
'notnull'=>1,
'position'=>500),
422 'tms' =>array(
'type'=>
'timestamp',
'label'=>
'DateModification',
'enabled'=>1,
'visible'=>-2,
'notnull'=>1,
'position'=>501),
424 'fk_user_author'=>array(
'type'=>
'integer',
'label'=>
'UserAuthor',
'enabled'=>1,
'visible'=>-2,
'notnull'=>1,
'position'=>510,
'foreignkey'=>
'llx_user.rowid'),
425 'fk_user_modif' =>array(
'type'=>
'integer',
'label'=>
'UserModif',
'enabled'=>1,
'visible'=>-2,
'notnull'=>-1,
'position'=>511),
427 'import_key' =>array(
'type'=>
'varchar(14)',
'label'=>
'ImportId',
'enabled'=>1,
'visible'=>-2,
'notnull'=>-1,
'index'=>0,
'position'=>1000),
493 public function create($user, $notrigger = 0)
495 global $conf, $langs;
501 $this->label = trim($this->label);
502 $this->price_ttc =
price2num($this->price_ttc);
504 $this->price_min_ttc =
price2num($this->price_min_ttc);
505 $this->price_min =
price2num($this->price_min);
506 if (empty($this->tva_tx)) {
509 if (empty($this->tva_npr)) {
513 if (empty($this->localtax1_tx)) {
514 $this->localtax1_tx = 0;
516 if (empty($this->localtax2_tx)) {
517 $this->localtax2_tx = 0;
519 if (empty($this->localtax1_type)) {
520 $this->localtax1_type =
'0';
522 if (empty($this->localtax2_type)) {
523 $this->localtax2_type =
'0';
525 if (empty($this->
price)) {
528 if (empty($this->price_min)) {
529 $this->price_min = 0;
532 if (empty($this->price_by_qty)) {
533 $this->price_by_qty = 0;
536 if (empty($this->status)) {
539 if (empty($this->status_buy)) {
540 $this->status_buy = 0;
549 if ($this->price_base_type ==
'TTC' && $this->price_ttc > 0) {
550 $price_ttc =
price2num($this->price_ttc,
'MU');
551 $price_ht =
price2num($this->price_ttc / (1 + ($this->tva_tx / 100)),
'MU');
555 if ($this->price_base_type !=
'TTC' && $this->
price > 0) {
557 $price_ttc =
price2num($this->
price * (1 + ($this->tva_tx / 100)),
'MU');
561 if (($this->price_min_ttc > 0) && ($this->price_base_type ==
'TTC')) {
562 $price_min_ttc =
price2num($this->price_min_ttc,
'MU');
563 $price_min_ht =
price2num($this->price_min_ttc / (1 + ($this->tva_tx / 100)),
'MU');
567 if (($this->price_min > 0) && ($this->price_base_type !=
'TTC')) {
568 $price_min_ht =
price2num($this->price_min,
'MU');
569 $price_min_ttc =
price2num($this->price_min * (1 + ($this->tva_tx / 100)),
'MU');
572 $this->accountancy_code_buy = trim($this->accountancy_code_buy);
573 $this->accountancy_code_buy_intra = trim($this->accountancy_code_buy_intra);
574 $this->accountancy_code_buy_export = trim($this->accountancy_code_buy_export);
575 $this->accountancy_code_sell = trim($this->accountancy_code_sell);
576 $this->accountancy_code_sell_intra = trim($this->accountancy_code_sell_intra);
577 $this->accountancy_code_sell_export = trim($this->accountancy_code_sell_export);
580 $this->barcode = trim($this->barcode);
583 if (empty($this->label)) {
584 $this->error =
'ErrorMandatoryParametersNotProvided';
588 if (empty($this->ref) || $this->ref ==
'auto') {
590 $module = (!empty($conf->global->PRODUCT_CODEPRODUCT_ADDON) ? $conf->global->PRODUCT_CODEPRODUCT_ADDON :
'mod_codeproduct_leopard');
591 if ($module !=
'mod_codeproduct_leopard')
593 if (substr($module, 0, 16) ==
'mod_codeproduct_' && substr($module, -3) ==
'php') {
594 $module = substr($module, 0,
dol_strlen($module) - 4);
597 $modCodeProduct =
new $module;
598 if (!empty($modCodeProduct->code_auto)) {
599 $this->ref = $modCodeProduct->getNextValue($this, $this->
type);
601 unset($modCodeProduct);
604 if (empty($this->ref)) {
605 $this->error =
'ProductModuleNotSetupForAutoRef';
610 dol_syslog(get_class($this).
"::create ref=".$this->ref.
" price=".$this->price.
" price_ttc=".$this->price_ttc.
" tva_tx=".$this->tva_tx.
" price_base_type=".$this->price_base_type, LOG_DEBUG);
617 if ($this->barcode == -1) {
618 $this->barcode = $this->
get_barcode($this, $this->barcode_type_code);
623 $result = $this->
verify();
626 $sql =
"SELECT count(*) as nb";
627 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product";
628 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
629 $sql .=
" AND ref = '".$this->db->escape($this->ref).
"'";
631 $result = $this->
db->query($sql);
633 $obj = $this->
db->fetch_object($result);
636 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"product (";
641 $sql .=
", price_min";
642 $sql .=
", price_min_ttc";
644 $sql .=
", fk_user_author";
645 $sql .=
", fk_product_type";
647 $sql .=
", price_ttc";
648 $sql .=
", price_base_type";
651 $sql .=
", accountancy_code_buy";
652 $sql .=
", accountancy_code_buy_intra";
653 $sql .=
", accountancy_code_buy_export";
654 $sql .=
", accountancy_code_sell";
655 $sql .=
", accountancy_code_sell_intra";
656 $sql .=
", accountancy_code_sell_export";
658 $sql .=
", finished";
661 $sql .=
") VALUES (";
662 $sql .=
"'".$this->db->idate($now).
"'";
663 $sql .=
", ".$conf->entity;
664 $sql .=
", '".$this->db->escape($this->ref).
"'";
665 $sql .=
", ".(!empty($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
666 $sql .=
", ".price2num($price_min_ht);
667 $sql .=
", ".price2num($price_min_ttc);
668 $sql .=
", ".(!empty($this->label) ?
"'".$this->db->escape($this->label).
"'" :
"null");
669 $sql .=
", ".$user->id;
670 $sql .=
", ".$this->type;
671 $sql .=
", ".price2num($price_ht);
672 $sql .=
", ".price2num($price_ttc);
673 $sql .=
", '".$this->db->escape($this->price_base_type).
"'";
674 $sql .=
", ".$this->status;
675 $sql .=
", ".$this->status_buy;
676 $sql .=
", '".$this->db->escape($this->accountancy_code_buy).
"'";
677 $sql .=
", '".$this->db->escape($this->accountancy_code_buy_intra).
"'";
678 $sql .=
", '".$this->db->escape($this->accountancy_code_buy_export).
"'";
679 $sql .=
", '".$this->db->escape($this->accountancy_code_sell).
"'";
680 $sql .=
", '".$this->db->escape($this->accountancy_code_sell_intra).
"'";
681 $sql .=
", '".$this->db->escape($this->accountancy_code_sell_export).
"'";
682 $sql .=
", '".$this->db->escape($this->canvas).
"'";
683 $sql .=
", ".((!isset($this->finished) || $this->finished < 0 || $this->finished ==
'') ?
'null' : (
int) $this->finished);
684 $sql .=
", ".((empty($this->status_batch) || $this->status_batch < 0) ?
'0' : $this->status_batch);
685 $sql .=
", ".(!$this->fk_unit ?
'NULL' : $this->fk_unit);
688 dol_syslog(get_class($this).
"::Create", LOG_DEBUG);
689 $result = $this->
db->query($sql);
691 $id = $this->
db->last_insert_id(MAIN_DB_PREFIX.
"product");
695 $this->
price = $price_ht;
696 $this->price_ttc = $price_ttc;
697 $this->price_min = $price_min_ht;
698 $this->price_min_ttc = $price_min_ttc;
702 if ($this->
update($id, $user,
true,
'add') <= 0) {
707 $this->error = $this->
db->lasterror();
711 $this->error =
'ErrorFailedToGetInsertedId';
715 $this->error = $this->
db->lasterror();
719 $langs->load(
"products");
721 $this->error =
"ErrorProductAlreadyExists";
725 $this->error = $this->
db->lasterror();
728 if (!$error && !$notrigger) {
731 if ($result < 0) { $error++;
740 $this->
db->rollback();
744 $this->
db->rollback();
745 dol_syslog(get_class($this).
"::Create fails verify ".join(
',', $this->errors), LOG_WARNING);
759 $this->errors = array();
762 $this->ref = trim($this->ref);
765 $this->errors[] =
'ErrorBadRef';
769 $rescode = $this->
check_barcode($this->barcode, $this->barcode_type_code);
771 if ($rescode == -1) {
772 $this->errors[] =
'ErrorBadBarCodeSyntax';
773 } elseif ($rescode == -2) {
774 $this->errors[] =
'ErrorBarCodeRequired';
775 } elseif ($rescode == -3) {
777 $this->errors[] =
'ErrorBarCodeAlreadyUsed';
801 if (!empty($conf->barcode->enabled) && !empty($conf->global->BARCODE_PRODUCT_ADDON_NUM)) {
802 $module = strtolower($conf->global->BARCODE_PRODUCT_ADDON_NUM);
804 $dirsociete = array_merge(array(
'/core/modules/barcode/'), $conf->modules_parts[
'barcode']);
805 foreach ($dirsociete as $dirroot)
812 $mod =
new $module();
814 dol_syslog(get_class($this).
"::check_barcode value=".$valuetotest.
" type=".$typefortest.
" module=".$module);
815 $result = $mod->verif($this->
db, $valuetotest, $this, 0, $typefortest);
833 public function update($id, $user, $notrigger =
false, $action =
'update', $updatetype =
false)
835 global $langs, $conf, $hookmanager;
841 $this->label =
'MISSING LABEL';
846 $this->label = trim($this->label);
848 $this->
note = (isset($this->
note) ? trim($this->
note) : null);
849 $this->net_measure =
price2num($this->net_measure);
850 $this->net_measure_units = trim($this->net_measure_units);
851 $this->weight =
price2num($this->weight);
852 $this->weight_units = trim($this->weight_units);
853 $this->length =
price2num($this->length);
854 $this->length_units = trim($this->length_units);
856 $this->width_units = trim($this->width_units);
857 $this->height =
price2num($this->height);
858 $this->height_units = trim($this->height_units);
859 $this->surface =
price2num($this->surface);
860 $this->surface_units = trim($this->surface_units);
861 $this->volume =
price2num($this->volume);
862 $this->volume_units = trim($this->volume_units);
865 if (is_numeric($this->length_units)) {
866 $this->width_units = $this->length_units;
868 if (is_numeric($this->length_units)) {
869 $this->height_units = $this->length_units;
873 if (empty($this->surface) && !empty($this->length) && !empty($this->width) && $this->length_units == $this->width_units) {
874 $this->surface = $this->length * $this->width;
877 if (empty($this->volume) && !empty($this->surface) && !empty($this->height) && $this->length_units == $this->height_units) {
878 $this->volume = $this->surface * $this->height;
882 if (empty($this->tva_tx)) {
885 if (empty($this->tva_npr)) {
888 if (empty($this->localtax1_tx)) {
889 $this->localtax1_tx = 0;
891 if (empty($this->localtax2_tx)) {
892 $this->localtax2_tx = 0;
894 if (empty($this->localtax1_type)) {
895 $this->localtax1_type =
'0';
897 if (empty($this->localtax2_type)) {
898 $this->localtax2_type =
'0';
900 if (empty($this->status)) {
903 if (empty($this->status_buy)) {
904 $this->status_buy = 0;
907 if (empty($this->country_id)) {
908 $this->country_id = 0;
911 if (empty($this->state_id)) {
916 $this->barcode = trim($this->barcode);
918 $this->accountancy_code_buy = trim($this->accountancy_code_buy);
919 $this->accountancy_code_buy_intra = trim($this->accountancy_code_buy_intra);
920 $this->accountancy_code_buy_export = trim($this->accountancy_code_buy_export);
921 $this->accountancy_code_sell = trim($this->accountancy_code_sell);
922 $this->accountancy_code_sell_intra = trim($this->accountancy_code_sell_intra);
923 $this->accountancy_code_sell_export = trim($this->accountancy_code_sell_export);
931 if ($action !=
'add') {
932 $result = $this->
verify();
939 if (empty($this->oldcopy)) {
940 $org =
new self($this->db);
941 $org->fetch($this->
id);
942 $this->oldcopy = $org;
947 if ($this->
hasbatch() && !$this->oldcopy->hasbatch()) {
949 $valueforundefinedlot =
'000000';
950 if (!empty($conf->global->STOCK_DEFAULT_BATCH)) $valueforundefinedlot = $conf->global->STOCK_DEFAULT_BATCH;
952 dol_syslog(
"Flag batch of product id=".$this->
id.
" is set to ON, so we will create missing records into product_batch");
955 foreach ($this->stock_warehouse as $idW => $ObjW)
958 foreach ($ObjW->detail_batch as $detail)
960 if ($detail->batch == $valueforundefinedlot || $detail->batch ==
'Undefined') {
962 $sqlclean =
"DELETE FROM ".MAIN_DB_PREFIX.
"product_batch WHERE batch in('Undefined', '".$this->
db->escape($valueforundefinedlot).
"') AND fk_product_stock = ".$ObjW->id;
963 $result = $this->
db->query($sqlclean);
971 $qty_batch += $detail->qty;
975 if ($ObjW->real <> $qty_batch) {
977 $ObjBatch->batch = $valueforundefinedlot;
978 $ObjBatch->qty = ($ObjW->real - $qty_batch);
979 $ObjBatch->fk_product_stock = $ObjW->id;
981 if ($ObjBatch->create($user, 1) < 0) {
983 $this->errors = $ObjBatch->errors;
990 if ($this->barcode == -1) { $this->barcode = $this->
get_barcode($this, $this->barcode_type_code);
993 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"product";
994 $sql .=
" SET label = '".$this->db->escape($this->label).
"'";
997 $sql .=
", fk_product_type = ".$this->type;
1000 $sql .=
", ref = '".$this->db->escape($this->ref).
"'";
1001 $sql .=
", ref_ext = ".(!empty($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
1002 $sql .=
", default_vat_code = ".($this->default_vat_code ?
"'".$this->db->escape($this->default_vat_code).
"'" :
"null");
1003 $sql .=
", tva_tx = ".$this->tva_tx;
1004 $sql .=
", recuperableonly = ".$this->tva_npr;
1005 $sql .=
", localtax1_tx = ".$this->localtax1_tx;
1006 $sql .=
", localtax2_tx = ".$this->localtax2_tx;
1007 $sql .=
", localtax1_type = ".($this->localtax1_type !=
'' ?
"'".$this->db->escape($this->localtax1_type).
"'" :
"'0'");
1008 $sql .=
", localtax2_type = ".($this->localtax2_type !=
'' ?
"'".$this->db->escape($this->localtax2_type).
"'" :
"'0'");
1010 $sql .=
", barcode = ".(empty($this->barcode) ?
"null" :
"'".$this->db->escape($this->barcode).
"'");
1011 $sql .=
", fk_barcode_type = ".(empty($this->barcode_type) ?
"null" : $this->
db->escape($this->barcode_type));
1013 $sql .=
", tosell = ".(int) $this->status;
1014 $sql .=
", tobuy = ".(int) $this->status_buy;
1015 $sql .=
", tobatch = ".((empty($this->status_batch) || $this->status_batch < 0) ?
'0' : (
int) $this->status_batch);
1016 $sql .=
", finished = ".((!isset($this->finished) || $this->finished < 0 || $this->finished ==
'') ?
"null" : (
int) $this->finished);
1017 $sql .=
", net_measure = ".($this->net_measure !=
'' ?
"'".$this->db->escape($this->net_measure).
"'" :
'null');
1018 $sql .=
", net_measure_units = ".($this->net_measure_units !=
'' ?
"'".$this->db->escape($this->net_measure_units).
"'" :
'null');
1019 $sql .=
", weight = ".($this->weight !=
'' ?
"'".$this->db->escape($this->weight).
"'" :
'null');
1020 $sql .=
", weight_units = ".($this->weight_units !=
'' ?
"'".$this->db->escape($this->weight_units).
"'" :
'null');
1021 $sql .=
", length = ".($this->length !=
'' ?
"'".$this->db->escape($this->length).
"'" :
'null');
1022 $sql .=
", length_units = ".($this->length_units !=
'' ?
"'".$this->db->escape($this->length_units).
"'" :
'null');
1023 $sql .=
", width= ".($this->width !=
'' ?
"'".$this->db->escape($this->width).
"'" :
'null');
1024 $sql .=
", width_units = ".($this->width_units !=
'' ?
"'".$this->db->escape($this->width_units).
"'" :
'null');
1025 $sql .=
", height = ".($this->height !=
'' ?
"'".$this->db->escape($this->height).
"'" :
'null');
1026 $sql .=
", height_units = ".($this->height_units !=
'' ?
"'".$this->db->escape($this->height_units).
"'" :
'null');
1027 $sql .=
", surface = ".($this->surface !=
'' ?
"'".$this->db->escape($this->surface).
"'" :
'null');
1028 $sql .=
", surface_units = ".($this->surface_units !=
'' ?
"'".$this->db->escape($this->surface_units).
"'" :
'null');
1029 $sql .=
", volume = ".($this->volume !=
'' ?
"'".$this->db->escape($this->volume).
"'" :
'null');
1030 $sql .=
", volume_units = ".($this->volume_units !=
'' ?
"'".$this->db->escape($this->volume_units).
"'" :
'null');
1031 $sql .=
", fk_default_warehouse = ".($this->fk_default_warehouse > 0 ? $this->
db->escape($this->fk_default_warehouse) :
'null');
1032 $sql .=
", seuil_stock_alerte = ".((isset($this->seuil_stock_alerte) && is_numeric($this->seuil_stock_alerte)) ? (
float) $this->seuil_stock_alerte :
'null');
1033 $sql .=
", description = '".$this->db->escape($this->
description).
"'";
1034 $sql .=
", url = ".($this->url ?
"'".$this->db->escape($this->url).
"'" :
'null');
1035 $sql .=
", customcode = '".$this->db->escape($this->customcode).
"'";
1036 $sql .=
", fk_country = ".($this->country_id > 0 ? (int) $this->country_id :
'null');
1037 $sql .=
", fk_state = ".($this->state_id > 0 ? (int) $this->state_id :
'null');
1038 $sql .=
", note = ".(isset($this->
note) ?
"'".$this->db->escape($this->
note).
"'" :
'null');
1039 $sql .=
", duration = '".$this->db->escape($this->duration_value.$this->duration_unit).
"'";
1040 $sql .=
", accountancy_code_buy = '".$this->db->escape($this->accountancy_code_buy).
"'";
1041 $sql .=
", accountancy_code_buy_intra = '".$this->db->escape($this->accountancy_code_buy_intra).
"'";
1042 $sql .=
", accountancy_code_buy_export = '".$this->db->escape($this->accountancy_code_buy_export).
"'";
1043 $sql .=
", accountancy_code_sell= '".$this->db->escape($this->accountancy_code_sell).
"'";
1044 $sql .=
", accountancy_code_sell_intra= '".$this->db->escape($this->accountancy_code_sell_intra).
"'";
1045 $sql .=
", accountancy_code_sell_export= '".$this->db->escape($this->accountancy_code_sell_export).
"'";
1046 $sql .=
", desiredstock = ".((isset($this->desiredstock) && is_numeric($this->desiredstock)) ? (
float) $this->desiredstock :
"null");
1047 $sql .=
", cost_price = ".($this->cost_price !=
'' ? $this->
db->escape($this->cost_price) :
'null');
1048 $sql .=
", fk_unit= ".(!$this->fk_unit ?
'NULL' : (int) $this->fk_unit);
1049 $sql .=
", price_autogen = ".(!$this->price_autogen ? 0 : 1);
1050 $sql .=
", fk_price_expression = ".($this->fk_price_expression != 0 ? (int) $this->fk_price_expression :
'NULL');
1051 $sql .=
", fk_user_modif = ".($user->id > 0 ? $user->id :
'NULL');
1054 $sql .=
" WHERE rowid = ".$id;
1056 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
1063 if (!empty($conf->global->MAIN_MULTILANGS)) {
1065 $this->error = $langs->trans(
"Error").
" : ".$this->
db->error().
" - ".$sql;
1080 if (!$error && !$notrigger) {
1082 $result = $this->
call_trigger(
'PRODUCT_MODIFY', $user);
1089 if (!$error && (is_object($this->oldcopy) && $this->oldcopy->ref !== $this->ref)) {
1091 if ($conf->product->dir_output) {
1094 if (file_exists($olddir)) {
1098 $res = @rename($olddir, $newdir);
1100 $langs->load(
"errors");
1101 $this->error = $langs->trans(
'ErrorFailToRenameDir', $olddir, $newdir);
1109 if (!empty($conf->variants->enabled)) {
1110 include_once DOL_DOCUMENT_ROOT.
'/variants/class/ProductCombination.class.php';
1114 foreach ($comb->fetchAllByFkProductParent($this->id) as $currcomb) {
1115 $currcomb->updateProperties($this, $user);
1119 $this->
db->commit();
1122 $this->
db->rollback();
1126 if ($this->
db->errno() ==
'DB_ERROR_RECORD_ALREADY_EXISTS') {
1127 $langs->load(
"errors");
1128 if (empty($conf->barcode->enabled) || empty($this->barcode)) {
1129 $this->error = $langs->trans(
"Error").
" : ".$langs->trans(
"ErrorProductAlreadyExists", $this->ref);
1131 $this->error = $langs->trans(
"Error").
" : ".$langs->trans(
"ErrorProductBarCodeAlreadyExists", $this->barcode);
1133 $this->errors[] = $this->error;
1134 $this->
db->rollback();
1137 $this->error = $langs->trans(
"Error").
" : ".$this->
db->error().
" - ".$sql;
1138 $this->errors[] = $this->error;
1139 $this->
db->rollback();
1144 $this->
db->rollback();
1145 dol_syslog(get_class($this).
"::Update fails verify ".join(
',', $this->errors), LOG_WARNING);
1157 public function delete(
User $user, $notrigger = 0)
1159 global $conf, $langs;
1160 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1165 if (empty($this->
id)) {
1166 $this->error =
"Object must be fetched before calling delete";
1170 $this->error =
"ErrorForbidden";
1175 if (empty($objectisused)) {
1178 if (!$error && empty($notrigger)) {
1180 $result = $this->
call_trigger(
'PRODUCT_DELETE', $user);
1189 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
'product_batch';
1190 $sql .=
" WHERE fk_product_stock IN (";
1191 $sql .=
"SELECT rowid FROM ".MAIN_DB_PREFIX.
'product_stock';
1192 $sql .=
" WHERE fk_product = ".(int) $this->
id.
")";
1194 $result = $this->
db->query($sql);
1197 $this->errors[] = $this->
db->lasterror();
1203 $elements = array(
'product_fournisseur_price',
'product_price',
'product_lang',
'categorie_product',
'product_stock',
'product_customer_price',
'product_lot');
1204 foreach ($elements as $table)
1207 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.$table;
1208 $sql .=
" WHERE fk_product = ".(int) $this->
id;
1210 $result = $this->
db->query($sql);
1213 $this->errors[] = $this->
db->lasterror();
1220 include_once DOL_DOCUMENT_ROOT.
'/variants/class/ProductCombination.class.php';
1221 include_once DOL_DOCUMENT_ROOT.
'/variants/class/ProductCombination2ValuePair.class.php';
1226 if ($prodcomb->deleteByFkProductParent($user, $this->id) < 0) {
1228 $this->errors[] =
'Error deleting combinations';
1232 if (!$error && ($prodcomb->fetchByFkProductChild($this->id) > 0) && ($prodcomb->delete($user) < 0)) {
1234 $this->errors[] =
'Error deleting child combination';
1240 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"product_association";
1241 $sql .=
" WHERE fk_product_pere = ".(int) $this->
id.
" OR fk_product_fils = ".(
int) $this->id;
1243 $result = $this->
db->query($sql);
1246 $this->errors[] = $this->
db->lasterror();
1255 dol_syslog(get_class($this).
"::delete error -4 ".$this->error, LOG_ERR);
1261 $sqlz =
"DELETE FROM ".MAIN_DB_PREFIX.
"product";
1262 $sqlz .=
" WHERE rowid = ".(int) $this->
id;
1264 $resultz = $this->
db->query($sqlz);
1267 $this->errors[] = $this->
db->lasterror();
1274 if ($conf->product->dir_output) {
1275 $dir = $conf->product->dir_output.
"/".$ref;
1276 if (file_exists($dir)) {
1279 $this->errors[] =
'ErrorFailToDeleteDir';
1287 $this->
db->commit();
1290 foreach ($this->errors as $errmsg)
1292 dol_syslog(get_class($this).
"::delete ".$errmsg, LOG_ERR);
1293 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1295 $this->
db->rollback();
1299 $this->error =
"ErrorRecordIsUsedCantDelete";
1312 global $conf, $langs;
1314 $langs_available = $langs->get_available_languages(DOL_DOCUMENT_ROOT, 0, 2);
1315 $current_lang = $langs->getDefaultLang();
1317 foreach ($langs_available as $key => $value)
1319 if ($key == $current_lang) {
1320 $sql =
"SELECT rowid";
1321 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product_lang";
1322 $sql .=
" WHERE fk_product=".$this->id;
1323 $sql .=
" AND lang='".$this->db->escape($key).
"'";
1325 $result = $this->
db->query($sql);
1327 if ($this->
db->num_rows($result))
1329 $sql2 =
"UPDATE ".MAIN_DB_PREFIX.
"product_lang";
1331 $sql2 .=
" label='".$this->db->escape($this->label).
"',";
1332 $sql2 .=
" description='".$this->db->escape($this->
description).
"'";
1333 if (!empty($conf->global->PRODUCT_USE_OTHER_FIELD_IN_TRANSLATION)) { $sql2 .=
", note='".$this->db->escape($this->other).
"'";
1335 $sql2 .=
" WHERE fk_product=".$this->id.
" AND lang='".$this->
db->escape($key).
"'";
1337 $sql2 =
"INSERT INTO ".MAIN_DB_PREFIX.
"product_lang (fk_product, lang, label, description";
1338 if (!empty($conf->global->PRODUCT_USE_OTHER_FIELD_IN_TRANSLATION)) { $sql2 .=
", note";
1341 $sql2 .=
" VALUES(".$this->id.
",'".$this->
db->escape($key).
"','".$this->
db->escape($this->label).
"',";
1342 $sql2 .=
" '".$this->db->escape($this->
description).
"'";
1343 if (!empty($conf->global->PRODUCT_USE_OTHER_FIELD_IN_TRANSLATION)) {
1344 $sql2 .=
", '".$this->db->escape($this->other).
"'";
1348 dol_syslog(get_class($this).
'::setMultiLangs key = current_lang = '.$key);
1349 if (!$this->
db->query($sql2)) {
1350 $this->error = $this->
db->lasterror();
1353 } elseif (isset($this->multilangs[$key])) {
1354 $sql =
"SELECT rowid";
1355 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product_lang";
1356 $sql .=
" WHERE fk_product=".$this->id;
1357 $sql .=
" AND lang='".$this->db->escape($key).
"'";
1359 $result = $this->
db->query($sql);
1361 if ($this->
db->num_rows($result))
1363 $sql2 =
"UPDATE ".MAIN_DB_PREFIX.
"product_lang";
1365 $sql2 .=
" label='".$this->db->escape($this->multilangs[
"$key"][
"label"]).
"',";
1366 $sql2 .=
" description='".$this->db->escape($this->multilangs[
"$key"][
"description"]).
"'";
1367 if (!empty($conf->global->PRODUCT_USE_OTHER_FIELD_IN_TRANSLATION)) {
1368 $sql2 .=
", note='".$this->db->escape($this->multilangs[
"$key"][
"other"]).
"'";
1370 $sql2 .=
" WHERE fk_product=".$this->id.
" AND lang='".$this->
db->escape($key).
"'";
1372 $sql2 =
"INSERT INTO ".MAIN_DB_PREFIX.
"product_lang (fk_product, lang, label, description";
1373 if (!empty($conf->global->PRODUCT_USE_OTHER_FIELD_IN_TRANSLATION)) { $sql2 .=
", note";
1376 $sql2 .=
" VALUES(".$this->id.
",'".$this->
db->escape($key).
"','".$this->
db->escape($this->multilangs[
"$key"][
"label"]).
"',";
1377 $sql2 .=
" '".$this->db->escape($this->multilangs[
"$key"][
"description"]).
"'";
1378 if (!empty($conf->global->PRODUCT_USE_OTHER_FIELD_IN_TRANSLATION)) {
1379 $sql2 .=
", '".$this->db->escape($this->multilangs[
"$key"][
"other"]).
"'";
1385 if ($this->multilangs[
"$key"][
"label"] || $this->multilangs[
"$key"][
"description"]) {
1386 if (!$this->
db->query($sql2)) {
1387 $this->error = $this->
db->lasterror();
1397 $result = $this->
call_trigger(
'PRODUCT_SET_MULTILANGS', $user);
1399 $this->error = $this->
db->lasterror();
1417 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"product_lang";
1418 $sql .=
" WHERE fk_product=".$this->id.
" AND lang='".$this->
db->escape($langtodelete).
"'";
1420 dol_syslog(get_class($this).
'::delMultiLangs', LOG_DEBUG);
1421 $result = $this->
db->query($sql);
1424 $result = $this->
call_trigger(
'PRODUCT_DEL_MULTILANGS', $user);
1426 $this->error = $this->
db->lasterror();
1427 dol_syslog(get_class($this).
'::delMultiLangs error='.$this->error, LOG_ERR);
1433 $this->error = $this->
db->lasterror();
1434 dol_syslog(get_class($this).
'::delMultiLangs error='.$this->error, LOG_ERR);
1449 global $user, $langs, $conf;
1455 if ($type ==
'buy') {
1456 $field =
'accountancy_code_buy';
1457 } elseif ($type ==
'buy_intra') {
1458 $field =
'accountancy_code_buy_intra';
1459 } elseif ($type ==
'buy_export') {
1460 $field =
'accountancy_code_buy_export';
1461 } elseif ($type ==
'sell') {
1462 $field =
'accountancy_code_sell';
1463 } elseif ($type ==
'sell_intra') {
1464 $field =
'accountancy_code_sell_intra';
1465 } elseif ($type ==
'sell_export') {
1466 $field =
'accountancy_code_sell_export';
1471 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element.
" SET ";
1472 $sql .=
"$field = '".$this->db->escape($value).
"'";
1473 $sql .=
" WHERE rowid = ".$this->id;
1475 dol_syslog(__METHOD__.
" sql=".$sql, LOG_DEBUG);
1480 $result = $this->
call_trigger(
'PRODUCT_MODIFY', $user);
1481 if ($result < 0) $error++;
1485 $this->
db->rollback();
1489 $this->$field = $value;
1491 $this->
db->commit();
1494 $this->error = $this->
db->lasterror();
1495 $this->
db->rollback();
1509 $current_lang = $langs->getDefaultLang();
1511 $sql =
"SELECT lang, label, description, note as other";
1512 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product_lang";
1513 $sql .=
" WHERE fk_product=".$this->id;
1515 $result = $this->
db->query($sql);
1517 while ($obj = $this->
db->fetch_object($result))
1520 if ($obj->lang == $current_lang)
1522 $this->label = $obj->label;
1524 $this->other = $obj->other;
1526 $this->multilangs[
"$obj->lang"][
"label"] = $obj->label;
1527 $this->multilangs[
"$obj->lang"][
"description"] = $obj->description;
1528 $this->multilangs[
"$obj->lang"][
"other"] = $obj->other;
1532 $this->error =
"Error: ".$this->db->lasterror().
" - ".$sql;
1555 if (empty($this->price_by_qty)) {
1556 $this->price_by_qty = 0;
1560 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"product_price(price_level,date_price, fk_product, fk_user_author, price, price_ttc, price_base_type,tosell, tva_tx, default_vat_code, recuperableonly,";
1561 $sql .=
" localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, price_min,price_min_ttc,price_by_qty,entity,fk_price_expression) ";
1562 $sql .=
" VALUES(".($level ? $level : 1).
", '".$this->
db->idate($now).
"',".$this->
id.
",".$user->id.
",".$this->
price.
",".$this->price_ttc.
",'".$this->
db->escape($this->price_base_type).
"',".$this->status.
",".$this->tva_tx.
", ".($this->default_vat_code ? (
"'".$this->db->escape($this->default_vat_code).
"'") :
"null").
",".$this->tva_npr.
",";
1563 $sql .=
" ".$this->localtax1_tx.
", ".$this->localtax2_tx.
", '".$this->db->escape($this->localtax1_type).
"', '".$this->
db->escape($this->localtax2_type).
"', ".$this->price_min.
",".$this->price_min_ttc.
",".$this->price_by_qty.
",".$conf->entity.
",".($this->fk_price_expression > 0 ? $this->fk_price_expression :
'null');
1566 dol_syslog(get_class($this).
"::_log_price", LOG_DEBUG);
1569 $this->error = $this->
db->lasterror();
1589 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"product_price_by_qty";
1590 $sql .=
" WHERE fk_product_price=".$rowid;
1593 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"product_price";
1594 $sql .=
" WHERE rowid=".$rowid;
1599 $this->error = $this->
db->lasterror();
1614 public function getSellPrice($thirdparty_seller, $thirdparty_buyer, $pqp = 0)
1623 $pu_ht = $this->price;
1624 $pu_ttc = $this->price_ttc;
1625 $price_min = $this->price_min;
1626 $price_base_type = $this->price_base_type;
1629 if (!empty($conf->global->PRODUIT_MULTIPRICES) && !empty($thirdparty_buyer->price_level)) {
1630 $pu_ht = $this->multiprices[$thirdparty_buyer->price_level];
1631 $pu_ttc = $this->multiprices_ttc[$thirdparty_buyer->price_level];
1632 $price_min = $this->multiprices_min[$thirdparty_buyer->price_level];
1633 $price_base_type = $this->multiprices_base_type[$thirdparty_buyer->price_level];
1634 if (!empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL))
1636 if (isset($this->multiprices_tva_tx[$thirdparty_buyer->price_level]))
$tva_tx = $this->multiprices_tva_tx[$thirdparty_buyer->price_level];
1637 if (isset($this->multiprices_recuperableonly[$thirdparty_buyer->price_level]))
$tva_npr = $this->multiprices_recuperableonly[$thirdparty_buyer->price_level];
1640 } elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
1642 require_once DOL_DOCUMENT_ROOT.
'/product/class/productcustomerprice.class.php';
1646 $filter = array(
't.fk_product' => $this->
id,
't.fk_soc' => $thirdparty_buyer->id);
1648 $result = $prodcustprice->fetch_all(
'',
'', 0, 0, $filter);
1650 if (count($prodcustprice->lines) > 0) {
1651 $pu_ht =
price($prodcustprice->lines[0]->price);
1652 $price_min =
price($prodcustprice->lines[0]->price_min);
1653 $pu_ttc =
price($prodcustprice->lines[0]->price_ttc);
1654 $price_base_type = $prodcustprice->lines[0]->price_base_type;
1655 $tva_tx = $prodcustprice->lines[0]->tva_tx;
1656 if ($prodcustprice->lines[0]->default_vat_code && !preg_match(
'/\(.*\)/',
$tva_tx))
$tva_tx .=
' ('.$prodcustprice->lines[0]->default_vat_code.
')';
1657 $tva_npr = $prodcustprice->lines[0]->recuperableonly;
1661 } elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) {
1663 if ($this->prices_by_qty[0]) {
1666 foreach ($this->prices_by_qty_list[0] as $priceforthequantityarray) {
1667 if ($priceforthequantityarray[
'rowid'] != $pqp)
continue;
1669 if ($priceforthequantityarray[
'price_base_type'] ==
'HT')
1671 $pu_ht = $priceforthequantityarray[
'unitprice'];
1673 $pu_ttc = $priceforthequantityarray[
'unitprice'];
1678 } elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) {
1680 if ($this->prices_by_qty[$thirdparty_buyer->price_level]) {
1683 foreach ($this->prices_by_qty_list[$thirdparty_buyer->price_level] as $priceforthequantityarray)
1685 if ($priceforthequantityarray[
'rowid'] != $pqp)
continue;
1687 if ($priceforthequantityarray[
'price_base_type'] ==
'HT')
1689 $pu_ht = $priceforthequantityarray[
'unitprice'];
1691 $pu_ttc = $priceforthequantityarray[
'unitprice'];
1698 return array(
'pu_ht'=>$pu_ht,
'pu_ttc'=>$pu_ttc,
'price_min'=>$price_min,
'price_base_type'=>$price_base_type,
'tva_tx'=>
$tva_tx,
'tva_npr'=>
$tva_npr);
1715 public function get_buyprice($prodfournprice, $qty, $product_id = 0, $fourn_ref =
'', $fk_soc = 0)
1722 $sql =
"SELECT pfp.rowid, pfp.price as price, pfp.quantity as quantity, pfp.remise_percent,";
1723 $sql .=
" pfp.fk_product, pfp.ref_fourn, pfp.desc_fourn, pfp.fk_soc, pfp.tva_tx, pfp.fk_supplier_price_expression,";
1724 $sql .=
" pfp.default_vat_code,";
1725 $sql .=
" pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code";
1726 if (!empty($conf->global->PRODUCT_USE_SUPPLIER_PACKAGING)) $sql .=
", pfp.packaging";
1727 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product_fournisseur_price as pfp";
1728 $sql .=
" WHERE pfp.rowid = ".$prodfournprice;
1729 if ($qty > 0) { $sql .=
" AND pfp.quantity <= ".$qty;
1731 $sql .=
" ORDER BY pfp.quantity DESC";
1733 dol_syslog(get_class($this).
"::get_buyprice first search by prodfournprice/qty", LOG_DEBUG);
1736 $obj = $this->
db->fetch_object(
$resql);
1737 if ($obj && $obj->quantity > 0)
1739 if (!empty($conf->dynamicprices->enabled) && !empty($obj->fk_supplier_price_expression)) {
1740 include_once DOL_DOCUMENT_ROOT.
'/product/dynamic_price/class/price_parser.class.php';
1742 $prod_supplier->product_fourn_price_id = $obj->rowid;
1743 $prod_supplier->id = $obj->fk_product;
1744 $prod_supplier->fourn_qty = $obj->quantity;
1745 $prod_supplier->fourn_tva_tx = $obj->tva_tx;
1746 $prod_supplier->fk_supplier_price_expression = $obj->fk_supplier_price_expression;
1748 $price_result = $priceparser->parseProductSupplier($prod_supplier);
1749 if ($price_result >= 0) {
1750 $obj->price = $price_result;
1753 $this->product_fourn_price_id = $obj->rowid;
1754 $this->buyprice = $obj->price;
1755 $this->fourn_pu = $obj->price / $obj->quantity;
1756 $this->fourn_price_base_type =
'HT';
1757 $this->fourn_socid = $obj->fk_soc;
1758 $this->ref_fourn = $obj->ref_fourn;
1759 $this->ref_supplier = $obj->ref_fourn;
1760 $this->desc_supplier = $obj->desc_fourn;
1761 $this->remise_percent = $obj->remise_percent;
1762 $this->vatrate_supplier = $obj->tva_tx;
1763 $this->default_vat_code = $obj->default_vat_code;
1764 $this->fourn_multicurrency_price = $obj->multicurrency_price;
1765 $this->fourn_multicurrency_unitprice = $obj->multicurrency_unitprice;
1766 $this->fourn_multicurrency_tx = $obj->multicurrency_tx;
1767 $this->fourn_multicurrency_id = $obj->fk_multicurrency;
1768 $this->fourn_multicurrency_code = $obj->multicurrency_code;
1769 if (!empty($conf->global->PRODUCT_USE_SUPPLIER_PACKAGING)) $this->packaging = $obj->packaging;
1770 $result = $obj->fk_product;
1774 $sql =
"SELECT pfp.rowid, pfp.price as price, pfp.quantity as quantity, pfp.remise_percent, pfp.fk_soc,";
1775 $sql .=
" pfp.fk_product, pfp.ref_fourn as ref_supplier, pfp.desc_fourn as desc_supplier, pfp.tva_tx, pfp.fk_supplier_price_expression,";
1776 $sql .=
" pfp.default_vat_code,";
1777 $sql .=
" pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code,";
1778 $sql .=
" pfp.packaging";
1779 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product_fournisseur_price as pfp";
1780 $sql .=
" WHERE pfp.fk_product = ".$product_id;
1781 if ($fourn_ref !=
'none') { $sql .=
" AND pfp.ref_fourn = '".$this->db->escape($fourn_ref).
"'";
1783 if ($fk_soc > 0) { $sql .=
" AND pfp.fk_soc = ".$fk_soc;
1785 if ($qty > 0) { $sql .=
" AND pfp.quantity <= ".$qty;
1787 $sql .=
" ORDER BY pfp.quantity DESC";
1790 dol_syslog(get_class($this).
"::get_buyprice second search from qty/ref/product_id", LOG_DEBUG);
1793 $obj = $this->
db->fetch_object(
$resql);
1794 if ($obj && $obj->quantity > 0)
1796 if (!empty($conf->dynamicprices->enabled) && !empty($obj->fk_supplier_price_expression)) {
1797 include_once DOL_DOCUMENT_ROOT.
'/product/dynamic_price/class/price_parser.class.php';
1799 $prod_supplier->product_fourn_price_id = $obj->rowid;
1800 $prod_supplier->id = $obj->fk_product;
1801 $prod_supplier->fourn_qty = $obj->quantity;
1802 $prod_supplier->fourn_tva_tx = $obj->tva_tx;
1803 $prod_supplier->fk_supplier_price_expression = $obj->fk_supplier_price_expression;
1805 $price_result = $priceparser->parseProductSupplier($prod_supplier);
1807 $obj->price = $price_result;
1810 $this->product_fourn_price_id = $obj->rowid;
1811 $this->buyprice = $obj->price;
1812 $this->fourn_qty = $obj->quantity;
1813 $this->fourn_pu = $obj->price / $obj->quantity;
1814 $this->fourn_price_base_type =
'HT';
1815 $this->fourn_socid = $obj->fk_soc;
1816 $this->ref_fourn = $obj->ref_supplier;
1817 $this->ref_supplier = $obj->ref_supplier;
1818 $this->desc_supplier = $obj->desc_supplier;
1819 $this->remise_percent = $obj->remise_percent;
1820 $this->vatrate_supplier = $obj->tva_tx;
1821 $this->default_vat_code = $obj->default_vat_code;
1822 $this->fourn_multicurrency_price = $obj->multicurrency_price;
1823 $this->fourn_multicurrency_unitprice = $obj->multicurrency_unitprice;
1824 $this->fourn_multicurrency_tx = $obj->multicurrency_tx;
1825 $this->fourn_multicurrency_id = $obj->fk_multicurrency;
1826 $this->fourn_multicurrency_code = $obj->multicurrency_code;
1827 if (!empty($conf->global->PRODUCT_USE_SUPPLIER_PACKAGING)) $this->packaging = $obj->packaging;
1828 $result = $obj->fk_product;
1834 $this->error = $this->
db->lasterror();
1839 $this->error = $this->
db->lasterror();
1861 public function updatePrice($newprice, $newpricebase, $user, $newvat =
'', $newminprice = 0, $level = 0, $newnpr = 0, $newpbq = 0, $ignore_autogen = 0, $localtaxes_array = array(), $newdefaultvatcode =
'')
1863 global $conf, $langs;
1867 dol_syslog(get_class($this).
"::update_price id=".$id.
" newprice=".$newprice.
" newpricebase=".$newpricebase.
" newminprice=".$newminprice.
" level=".$level.
" npr=".$newnpr.
" newdefaultvatcode=".$newdefaultvatcode);
1870 if (empty($this->tva_tx)) {
1873 if (empty($newnpr)) {
1876 if (empty($newminprice)) {
1879 if (empty($newminprice)) {
1884 if ($newvat ==
'') {
1890 if ((!empty($conf->global->PRODUIT_MULTIPRICES) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) && !$ignore_autogen && $this->price_autogen && ($level == 1)) {
1891 return $this->
generateMultiprices($user, $newprice, $newpricebase, $newvat, $newnpr, $newpbq);
1894 if (!empty($newminprice) && ($newminprice > $newprice)) {
1895 $this->error =
'ErrorPriceCantBeLowerThanMinPrice';
1899 if ($newprice !==
'' || $newprice === 0) {
1900 if ($newpricebase ==
'TTC') {
1901 $price_ttc =
price2num($newprice,
'MU');
1902 $price =
price2num($newprice) / (1 + ($newvat / 100));
1905 if ($newminprice !=
'' || $newminprice == 0) {
1906 $price_min_ttc =
price2num($newminprice,
'MU');
1907 $price_min =
price2num($newminprice) / (1 + ($newvat / 100));
1908 $price_min =
price2num($price_min,
'MU');
1915 $price_ttc = ($newnpr != 1) ?
price2num($newprice) * (1 + ($newvat / 100)) : $price;
1916 $price_ttc =
price2num($price_ttc,
'MU');
1918 if ($newminprice !==
'' || $newminprice === 0) {
1919 $price_min =
price2num($newminprice,
'MU');
1920 $price_min_ttc =
price2num($newminprice) * (1 + ($newvat / 100));
1921 $price_min_ttc =
price2num($price_min_ttc,
'MU');
1930 if (count($localtaxes_array) > 0) {
1931 $localtaxtype1 = $localtaxes_array[
'0'];
1932 $localtax1 = $localtaxes_array[
'1'];
1933 $localtaxtype2 = $localtaxes_array[
'2'];
1934 $localtax2 = $localtaxes_array[
'3'];
1937 $localtaxtype1 =
'0';
1939 $localtaxtype2 =
'0';
1942 if (empty($localtax1)) {
1945 if (empty($localtax2)) {
1953 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"product SET";
1954 $sql .=
" price_base_type='".$this->db->escape($newpricebase).
"',";
1955 $sql .=
" price=".$price.
",";
1956 $sql .=
" price_ttc=".$price_ttc.
",";
1957 $sql .=
" price_min=".$price_min.
",";
1958 $sql .=
" price_min_ttc=".$price_min_ttc.
",";
1959 $sql .=
" localtax1_tx=".($localtax1 >= 0 ? $localtax1 :
'NULL').
",";
1960 $sql .=
" localtax2_tx=".($localtax2 >= 0 ? $localtax2 :
'NULL').
",";
1961 $sql .=
" localtax1_type=".($localtaxtype1 !=
'' ?
"'".$this->db->escape($localtaxtype1).
"'" :
"'0'").
",";
1962 $sql .=
" localtax2_type=".($localtaxtype2 !=
'' ?
"'".$this->db->escape($localtaxtype2).
"'" :
"'0'").
",";
1963 $sql .=
" default_vat_code=".($newdefaultvatcode ?
"'".$this->db->escape($newdefaultvatcode).
"'" :
"null").
",";
1964 $sql .=
" tva_tx='".price2num($newvat).
"',";
1965 $sql .=
" recuperableonly='".$this->db->escape($newnpr).
"'";
1966 $sql .=
" WHERE rowid = ".$id;
1968 dol_syslog(get_class($this).
"::update_price", LOG_DEBUG);
1971 $this->multiprices[$level] = $price;
1972 $this->multiprices_ttc[$level] = $price_ttc;
1973 $this->multiprices_min[$level] = $price_min;
1974 $this->multiprices_min_ttc[$level] = $price_min_ttc;
1975 $this->multiprices_base_type[$level] = $newpricebase;
1976 $this->multiprices_default_vat_code[$level] = $newdefaultvatcode;
1977 $this->multiprices_tva_tx[$level] = $newvat;
1978 $this->multiprices_recuperableonly[$level] = $newnpr;
1980 $this->
price = $price;
1981 $this->price_ttc = $price_ttc;
1982 $this->price_min = $price_min;
1983 $this->price_min_ttc = $price_min_ttc;
1984 $this->price_base_type = $newpricebase;
1985 $this->default_vat_code = $newdefaultvatcode;
1986 $this->tva_tx = $newvat;
1987 $this->tva_npr = $newnpr;
1989 $this->localtax1_tx = $localtax1;
1990 $this->localtax2_tx = $localtax2;
1991 $this->localtax1_type = $localtaxtype1;
1992 $this->localtax2_type = $localtaxtype2;
1995 $this->price_by_qty = $newpbq;
1999 $this->level = $level;
2002 $result = $this->
call_trigger(
'PRODUCT_PRICE_MODIFY', $user);
2004 $this->
db->rollback();
2009 $this->
db->commit();
2011 $this->
db->rollback();
2030 $this->fk_price_expression = $expression_id;
2032 return $this->
update($this->
id, $user);
2047 public function fetch($id =
'', $ref =
'', $ref_ext =
'', $barcode =
'', $ignore_expression = 0, $ignore_price_load = 0, $ignore_lang_load = 0)
2049 include_once DOL_DOCUMENT_ROOT.
'/core/lib/company.lib.php';
2051 global $langs, $conf;
2053 dol_syslog(get_class($this).
"::fetch id=".$id.
" ref=".$ref.
" ref_ext=".$ref_ext);
2056 if (!$id && !$ref && !$ref_ext && !$barcode) {
2057 $this->error =
'ErrorWrongParameters';
2058 dol_syslog(get_class($this).
"::fetch ".$this->error);
2062 $sql =
"SELECT rowid, ref, ref_ext, label, description, url, note_public, note as note_private, customcode, fk_country, fk_state, price, price_ttc,";
2063 $sql .=
" price_min, price_min_ttc, price_base_type, cost_price, default_vat_code, tva_tx, recuperableonly as tva_npr, localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, tosell,";
2064 $sql .=
" tobuy, fk_product_type, duration, fk_default_warehouse, seuil_stock_alerte, canvas, net_measure, net_measure_units, weight, weight_units,";
2065 $sql .=
" length, length_units, width, width_units, height, height_units,";
2066 $sql .=
" surface, surface_units, volume, volume_units, barcode, fk_barcode_type, finished,";
2067 $sql .=
" accountancy_code_buy, accountancy_code_buy_intra, accountancy_code_buy_export,";
2068 $sql .=
" accountancy_code_sell, accountancy_code_sell_intra, accountancy_code_sell_export, stock, pmp,";
2069 $sql .=
" datec, tms, import_key, entity, desiredstock, tobatch, fk_unit,";
2070 $sql .=
" fk_price_expression, price_autogen, model_pdf";
2071 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product";
2073 $sql .=
" WHERE rowid = ".(int) $id;
2075 $sql .=
" WHERE entity IN (".getEntity($this->element).
")";
2077 $sql .=
" AND ref = '".$this->db->escape($ref).
"'";
2078 } elseif ($ref_ext) {
2079 $sql .=
" AND ref_ext = '".$this->db->escape($ref_ext).
"'";
2080 } elseif ($barcode) {
2081 $sql .=
" AND barcode = '".$this->db->escape($barcode).
"'";
2087 unset($this->oldcopy);
2089 if ($this->
db->num_rows(
$resql) > 0) {
2090 $obj = $this->
db->fetch_object(
$resql);
2092 $this->
id = $obj->rowid;
2093 $this->ref = $obj->ref;
2094 $this->ref_ext = $obj->ref_ext;
2095 $this->label = $obj->label;
2097 $this->url = $obj->url;
2098 $this->note_public = $obj->note_public;
2099 $this->note_private = $obj->note_private;
2100 $this->
note = $obj->note_private;
2102 $this->
type = $obj->fk_product_type;
2103 $this->status = $obj->tosell;
2104 $this->status_buy = $obj->tobuy;
2105 $this->status_batch = $obj->tobatch;
2107 $this->customcode = $obj->customcode;
2108 $this->country_id = $obj->fk_country;
2109 $this->country_code =
getCountry($this->country_id, 2, $this->
db);
2110 $this->state_id = $obj->fk_state;
2111 $this->
price = $obj->price;
2112 $this->price_ttc = $obj->price_ttc;
2113 $this->price_min = $obj->price_min;
2114 $this->price_min_ttc = $obj->price_min_ttc;
2115 $this->price_base_type = $obj->price_base_type;
2116 $this->cost_price = $obj->cost_price;
2117 $this->default_vat_code = $obj->default_vat_code;
2118 $this->tva_tx = $obj->tva_tx;
2120 $this->tva_npr = $obj->tva_npr;
2121 $this->recuperableonly = $obj->tva_npr;
2123 $this->localtax1_tx = $obj->localtax1_tx;
2124 $this->localtax2_tx = $obj->localtax2_tx;
2125 $this->localtax1_type = $obj->localtax1_type;
2126 $this->localtax2_type = $obj->localtax2_type;
2128 $this->finished = $obj->finished;
2129 $this->duration = $obj->duration;
2130 $this->duration_value = substr($obj->duration, 0,
dol_strlen($obj->duration) - 1);
2131 $this->duration_unit = substr($obj->duration, -1);
2132 $this->canvas = $obj->canvas;
2133 $this->net_measure = $obj->net_measure;
2134 $this->net_measure_units = $obj->net_measure_units;
2135 $this->weight = $obj->weight;
2136 $this->weight_units = $obj->weight_units;
2137 $this->length = $obj->length;
2138 $this->length_units = $obj->length_units;
2139 $this->width = $obj->width;
2140 $this->width_units = $obj->width_units;
2141 $this->height = $obj->height;
2142 $this->height_units = $obj->height_units;
2144 $this->surface = $obj->surface;
2145 $this->surface_units = $obj->surface_units;
2146 $this->volume = $obj->volume;
2147 $this->volume_units = $obj->volume_units;
2148 $this->barcode = $obj->barcode;
2149 $this->barcode_type = $obj->fk_barcode_type;
2151 $this->accountancy_code_buy = $obj->accountancy_code_buy;
2152 $this->accountancy_code_buy_intra = $obj->accountancy_code_buy_intra;
2153 $this->accountancy_code_buy_export = $obj->accountancy_code_buy_export;
2154 $this->accountancy_code_sell = $obj->accountancy_code_sell;
2155 $this->accountancy_code_sell_intra = $obj->accountancy_code_sell_intra;
2156 $this->accountancy_code_sell_export = $obj->accountancy_code_sell_export;
2158 $this->fk_default_warehouse = $obj->fk_default_warehouse;
2159 $this->seuil_stock_alerte = $obj->seuil_stock_alerte;
2160 $this->desiredstock = $obj->desiredstock;
2161 $this->stock_reel = $obj->stock;
2162 $this->pmp = $obj->pmp;
2164 $this->date_creation = $obj->datec;
2165 $this->date_modification = $obj->tms;
2166 $this->import_key = $obj->import_key;
2167 $this->entity = $obj->entity;
2169 $this->ref_ext = $obj->ref_ext;
2170 $this->fk_price_expression = $obj->fk_price_expression;
2171 $this->fk_unit = $obj->fk_unit;
2172 $this->price_autogen = $obj->price_autogen;
2173 $this->model_pdf = $obj->model_pdf;
2182 if (!empty($conf->global->MAIN_MULTILANGS) && empty($ignore_lang_load)) {
2187 if (!empty($conf->global->PRODUIT_MULTIPRICES) && empty($ignore_price_load))
2189 for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++)
2191 $sql =
"SELECT price, price_ttc, price_min, price_min_ttc,";
2192 $sql .=
" price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid, recuperableonly";
2193 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product_price";
2194 $sql .=
" WHERE entity IN (".getEntity(
'productprice').
")";
2195 $sql .=
" AND price_level=".$i;
2196 $sql .=
" AND fk_product = ".$this->id;
2197 $sql .=
" ORDER BY date_price DESC, rowid DESC";
2201 $result = $this->
db->fetch_array(
$resql);
2203 $this->multiprices[$i] = $result ? $result[
"price"] : null;
2204 $this->multiprices_ttc[$i] = $result ? $result[
"price_ttc"] : null;
2205 $this->multiprices_min[$i] = $result ? $result[
"price_min"] : null;
2206 $this->multiprices_min_ttc[$i] = $result ? $result[
"price_min_ttc"] : null;
2207 $this->multiprices_base_type[$i] = $result ? $result[
"price_base_type"] : null;
2209 $this->multiprices_tva_tx[$i] = $result ? $result[
"tva_tx"].($result ?
' ('.$result[
'default_vat_code'].
')' :
'') : null;
2210 $this->multiprices_recuperableonly[$i] = $result ? $result[
"recuperableonly"] : null;
2248 $this->error = $this->
db->lasterror;
2252 } elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES) && empty($ignore_price_load))
2255 } elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) && empty($ignore_price_load))
2257 $sql =
"SELECT price, price_ttc, price_min, price_min_ttc,";
2258 $sql .=
" price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid";
2259 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product_price";
2260 $sql .=
" WHERE fk_product = ".$this->id;
2261 $sql .=
" ORDER BY date_price DESC, rowid DESC";
2265 $result = $this->
db->fetch_array(
$resql);
2268 $this->prices_by_qty[0] = $result[
"price_by_qty"];
2269 $this->prices_by_qty_id[0] = $result[
"rowid"];
2271 if ($this->prices_by_qty[0] == 1) {
2272 $sql =
"SELECT rowid,price, unitprice, quantity, remise_percent, remise, remise, price_base_type";
2273 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product_price_by_qty";
2274 $sql .=
" WHERE fk_product_price = ".$this->prices_by_qty_id[0];
2275 $sql .=
" ORDER BY quantity ASC";
2276 $resultat = array();
2280 while ($result = $this->
db->fetch_array(
$resql)) {
2281 $resultat[$ii] = array();
2282 $resultat[$ii][
"rowid"] = $result[
"rowid"];
2283 $resultat[$ii][
"price"] = $result[
"price"];
2284 $resultat[$ii][
"unitprice"] = $result[
"unitprice"];
2285 $resultat[$ii][
"quantity"] = $result[
"quantity"];
2286 $resultat[$ii][
"remise_percent"] = $result[
"remise_percent"];
2288 $resultat[$ii][
"price_base_type"] = $result[
"price_base_type"];
2291 $this->prices_by_qty_list[0] = $resultat;
2293 $this->error = $this->
db->lasterror;
2298 $this->error = $this->
db->lasterror;
2301 } elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES) && empty($ignore_price_load))
2303 for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++)
2305 $sql =
"SELECT price, price_ttc, price_min, price_min_ttc,";
2306 $sql .=
" price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid, recuperableonly";
2307 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product_price";
2308 $sql .=
" WHERE entity IN (".getEntity(
'productprice').
")";
2309 $sql .=
" AND price_level=".$i;
2310 $sql .=
" AND fk_product = ".$this->id;
2311 $sql .=
" ORDER BY date_price DESC, rowid DESC";
2315 $result = $this->
db->fetch_array(
$resql);
2317 $this->multiprices[$i] = $result[
"price"];
2318 $this->multiprices_ttc[$i] = $result[
"price_ttc"];
2319 $this->multiprices_min[$i] = $result[
"price_min"];
2320 $this->multiprices_min_ttc[$i] = $result[
"price_min_ttc"];
2321 $this->multiprices_base_type[$i] = $result[
"price_base_type"];
2323 $this->multiprices_tva_tx[$i] = $result[
"tva_tx"];
2324 $this->multiprices_recuperableonly[$i] = $result[
"recuperableonly"];
2327 $this->prices_by_qty[$i] = $result[
"price_by_qty"];
2328 $this->prices_by_qty_id[$i] = $result[
"rowid"];
2330 if ($this->prices_by_qty[$i] == 1) {
2331 $sql =
"SELECT rowid, price, unitprice, quantity, remise_percent, remise, price_base_type";
2332 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product_price_by_qty";
2333 $sql .=
" WHERE fk_product_price = ".$this->prices_by_qty_id[$i];
2334 $sql .=
" ORDER BY quantity ASC";
2335 $resultat = array();
2339 while ($result = $this->
db->fetch_array(
$resql)) {
2340 $resultat[$ii] = array();
2341 $resultat[$ii][
"rowid"] = $result[
"rowid"];
2342 $resultat[$ii][
"price"] = $result[
"price"];
2343 $resultat[$ii][
"unitprice"] = $result[
"unitprice"];
2344 $resultat[$ii][
"quantity"] = $result[
"quantity"];
2345 $resultat[$ii][
"remise_percent"] = $result[
"remise_percent"];
2346 $resultat[$ii][
"remise"] = $result[
"remise"];
2347 $resultat[$ii][
"price_base_type"] = $result[
"price_base_type"];
2350 $this->prices_by_qty_list[$i] = $resultat;
2352 $this->error = $this->
db->lasterror;
2357 $this->error = $this->
db->lasterror;
2363 if (!empty($conf->dynamicprices->enabled) && !empty($this->fk_price_expression) && empty($ignore_expression)) {
2364 include_once DOL_DOCUMENT_ROOT.
'/product/dynamic_price/class/price_parser.class.php';
2366 $price_result = $priceparser->parseProduct($this);
2367 if ($price_result >= 0) {
2368 $this->
price = $price_result;
2370 $this->price_ttc =
price2num($this->
price) * (1 + ($this->tva_tx / 100));
2371 $this->price_ttc =
price2num($this->price_ttc,
'MU');
2377 $this->stock_warehouse = array();
2384 $this->error = $this->
db->lasterror;
2399 global $user, $hookmanager, $action;
2403 foreach (array(
'toconsume',
'consumed',
'toproduce',
'produced') as $role) {
2404 $this->stats_mo[
'customers_'.$role] = 0;
2405 $this->stats_mo[
'nb_'.$role] = 0;
2406 $this->stats_mo[
'qty_'.$role] = 0;
2408 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,";
2409 $sql .=
" SUM(mp.qty) as qty";
2410 $sql .=
" FROM ".MAIN_DB_PREFIX.
"mrp_mo as c";
2411 $sql .=
" INNER JOIN ".MAIN_DB_PREFIX.
"mrp_production as mp ON mp.fk_mo=c.rowid";
2412 if (empty($user->rights->societe->client->voir) && !$socid) {
2413 $sql .=
"INNER JOIN ".MAIN_DB_PREFIX.
"societe_commerciaux as sc ON sc.fk_soc=c.fk_soc AND sc.fk_user = ".$user->id;
2416 $sql .=
" c.entity IN (".getEntity(
'mo').
")";
2418 $sql .=
" AND mp.fk_product =".$this->id;
2419 $sql .=
" AND mp.role ='".$this->db->escape($role).
"'";
2421 $sql .=
" AND c.fk_soc = ".$socid;
2424 $result = $this->
db->query($sql);
2426 $obj = $this->
db->fetch_object($result);
2427 $this->stats_mo[
'customers_'.$role] = $obj->nb_customers ? $obj->nb_customers : 0;
2428 $this->stats_mo[
'nb_'.$role] = $obj->nb ? $obj->nb : 0;
2429 $this->stats_mo[
'qty_'.$role] = $obj->qty ? $obj->qty : 0;
2431 $this->error = $this->
db->error();
2436 if (!empty($error)) {
2440 $parameters = array(
'socid' => $socid);
2441 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerMO', $parameters, $this, $action);
2442 if ($reshook > 0) $this->stats_mo = $hookmanager->resArray[
'stats_mo'];
2457 global $user, $hookmanager;
2461 $this->stats_bom[
'nb_toproduce'] = 0;
2462 $this->stats_bom[
'nb_toconsume'] = 0;
2463 $this->stats_bom[
'qty_toproduce'] = 0;
2464 $this->stats_bom[
'qty_toconsume'] = 0;
2466 $sql =
"SELECT COUNT(DISTINCT b.rowid) as nb_toproduce,";
2467 $sql .=
" SUM(b.qty) as qty_toproduce";
2468 $sql .=
" FROM ".MAIN_DB_PREFIX.
"bom_bom as b";
2469 $sql .=
" INNER JOIN ".MAIN_DB_PREFIX.
"bom_bomline as bl ON bl.fk_bom=b.rowid";
2471 $sql .=
" b.entity IN (".getEntity(
'bom').
")";
2472 $sql .=
" AND b.fk_product =".$this->id;
2473 $sql .=
" GROUP BY b.rowid";
2475 $result = $this->
db->query($sql);
2477 $obj = $this->
db->fetch_object($result);
2478 $this->stats_bom[
'nb_toproduce'] = $obj->nb_toproduce ? $obj->nb_toproduce : 0;
2479 $this->stats_bom[
'qty_toproduce'] = $obj->qty_toproduce ?
price2num($obj->qty_toproduce) : 0;
2481 $this->error = $this->
db->error();
2485 $sql =
"SELECT COUNT(DISTINCT bl.rowid) as nb_toconsume,";
2486 $sql .=
" SUM(bl.qty) as qty_toconsume";
2487 $sql .=
" FROM ".MAIN_DB_PREFIX.
"bom_bom as b";
2488 $sql .=
" INNER JOIN ".MAIN_DB_PREFIX.
"bom_bomline as bl ON bl.fk_bom=b.rowid";
2490 $sql .=
" b.entity IN (".getEntity(
'bom').
")";
2491 $sql .=
" AND bl.fk_product =".$this->id;
2493 $result = $this->
db->query($sql);
2495 $obj = $this->
db->fetch_object($result);
2496 $this->stats_bom[
'nb_toconsume'] = $obj->nb_toconsume ? $obj->nb_toconsume : 0;
2497 $this->stats_bom[
'qty_toconsume'] = $obj->qty_toconsume ?
price2num($obj->qty_toconsume) : 0;
2499 $this->error = $this->
db->error();
2503 if (!empty($error)) {
2507 $parameters = array(
'socid' => $socid);
2508 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerMO', $parameters, $this, $action);
2509 if ($reshook > 0) $this->stats_bom = $hookmanager->resArray[
'stats_bom'];
2524 global $conf, $user, $hookmanager;
2526 $sql =
"SELECT COUNT(DISTINCT p.fk_soc) as nb_customers, COUNT(DISTINCT p.rowid) as nb,";
2527 $sql .=
" COUNT(pd.rowid) as nb_rows, SUM(pd.qty) as qty";
2528 $sql .=
" FROM ".MAIN_DB_PREFIX.
"propaldet as pd";
2529 $sql .=
", ".MAIN_DB_PREFIX.
"propal as p";
2530 $sql .=
", ".MAIN_DB_PREFIX.
"societe as s";
2531 if (empty($user->rights->societe->client->voir) && !$socid) {
2532 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
2534 $sql .=
" WHERE p.rowid = pd.fk_propal";
2535 $sql .=
" AND p.fk_soc = s.rowid";
2536 $sql .=
" AND p.entity IN (".getEntity(
'propal').
")";
2537 $sql .=
" AND pd.fk_product = ".$this->id;
2538 if (empty($user->rights->societe->client->voir) && !$socid) {
2539 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
2543 $sql .=
" AND p.fk_soc = ".$socid;
2546 $result = $this->
db->query($sql);
2548 $obj = $this->
db->fetch_object($result);
2549 $this->stats_propale[
'customers'] = $obj->nb_customers;
2550 $this->stats_propale[
'nb'] = $obj->nb;
2551 $this->stats_propale[
'rows'] = $obj->nb_rows;
2552 $this->stats_propale[
'qty'] = $obj->qty ? $obj->qty : 0;
2555 if (!empty($conf->global->PRODUCT_STATS_WITH_PARENT_PROD_IF_INCDEC)) {
2557 if (is_array($TFather) && !empty($TFather)) {
2558 foreach ($TFather as &$fatherData) {
2560 $pFather->id = $fatherData[
'id'];
2561 $qtyCoef = $fatherData[
'qty'];
2563 if ($fatherData[
'incdec']) {
2564 $pFather->load_stats_propale($socid);
2566 $this->stats_propale[
'customers'] += $pFather->stats_propale[
'customers'];
2567 $this->stats_propale[
'nb'] += $pFather->stats_propale[
'nb'];
2568 $this->stats_propale[
'rows'] += $pFather->stats_propale[
'rows'];
2569 $this->stats_propale[
'qty'] += $pFather->stats_propale[
'qty'] * $qtyCoef;
2575 $parameters = array(
'socid' => $socid);
2576 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerProposal', $parameters, $this, $action);
2577 if ($reshook > 0) $this->stats_propale = $hookmanager->resArray[
'stats_propale'];
2581 $this->error = $this->
db->error();
2597 global $conf, $user, $hookmanager, $action;
2599 $sql =
"SELECT COUNT(DISTINCT p.fk_soc) as nb_suppliers, COUNT(DISTINCT p.rowid) as nb,";
2600 $sql .=
" COUNT(pd.rowid) as nb_rows, SUM(pd.qty) as qty";
2601 $sql .=
" FROM ".MAIN_DB_PREFIX.
"supplier_proposaldet as pd";
2602 $sql .=
", ".MAIN_DB_PREFIX.
"supplier_proposal as p";
2603 $sql .=
", ".MAIN_DB_PREFIX.
"societe as s";
2604 if (empty($user->rights->societe->client->voir) && !$socid) {
2605 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
2607 $sql .=
" WHERE p.rowid = pd.fk_supplier_proposal";
2608 $sql .=
" AND p.fk_soc = s.rowid";
2609 $sql .=
" AND p.entity IN (".getEntity(
'supplier_proposal').
")";
2610 $sql .=
" AND pd.fk_product = ".$this->id;
2611 if (empty($user->rights->societe->client->voir) && !$socid) {
2612 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
2616 $sql .=
" AND p.fk_soc = ".$socid;
2619 $result = $this->
db->query($sql);
2621 $obj = $this->
db->fetch_object($result);
2622 $this->stats_proposal_supplier[
'suppliers'] = $obj->nb_suppliers;
2623 $this->stats_proposal_supplier[
'nb'] = $obj->nb;
2624 $this->stats_proposal_supplier[
'rows'] = $obj->nb_rows;
2625 $this->stats_proposal_supplier[
'qty'] = $obj->qty ? $obj->qty : 0;
2627 $parameters = array(
'socid' => $socid);
2628 $reshook = $hookmanager->executeHooks(
'loadStatsSupplierProposal', $parameters, $this, $action);
2629 if ($reshook > 0) $this->stats_proposal_supplier = $hookmanager->resArray[
'stats_proposal_supplier'];
2633 $this->error = $this->
db->error();
2651 global $conf, $user, $hookmanager;
2653 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,";
2654 $sql .=
" COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty";
2655 $sql .=
" FROM ".MAIN_DB_PREFIX.
"commandedet as cd";
2656 $sql .=
", ".MAIN_DB_PREFIX.
"commande as c";
2657 $sql .=
", ".MAIN_DB_PREFIX.
"societe as s";
2658 if (empty($user->rights->societe->client->voir) && !$socid && !$forVirtualStock) {
2659 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
2661 $sql .=
" WHERE c.rowid = cd.fk_commande";
2662 $sql .=
" AND c.fk_soc = s.rowid";
2663 $sql .=
" AND c.entity IN (".getEntity($forVirtualStock && !empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ?
'stock' :
'commande').
")";
2664 $sql .=
" AND cd.fk_product = ".$this->id;
2665 if (empty($user->rights->societe->client->voir) && !$socid && !$forVirtualStock) {
2666 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
2669 $sql .=
" AND c.fk_soc = ".$socid;
2671 if ($filtrestatut <>
'') {
2672 $sql .=
" AND c.fk_statut in (".$this->db->sanitize($filtrestatut).
")";
2675 $result = $this->
db->query($sql);
2677 $obj = $this->
db->fetch_object($result);
2678 $this->stats_commande[
'customers'] = $obj->nb_customers;
2679 $this->stats_commande[
'nb'] = $obj->nb;
2680 $this->stats_commande[
'rows'] = $obj->nb_rows;
2681 $this->stats_commande[
'qty'] = $obj->qty ? $obj->qty : 0;
2684 if (!empty($conf->global->PRODUCT_STATS_WITH_PARENT_PROD_IF_INCDEC)) {
2686 if (is_array($TFather) && !empty($TFather)) {
2687 foreach ($TFather as &$fatherData) {
2689 $pFather->id = $fatherData[
'id'];
2690 $qtyCoef = $fatherData[
'qty'];
2692 if ($fatherData[
'incdec']) {
2693 $pFather->load_stats_commande($socid, $filtrestatut);
2695 $this->stats_commande[
'customers'] += $pFather->stats_commande[
'customers'];
2696 $this->stats_commande[
'nb'] += $pFather->stats_commande[
'nb'];
2697 $this->stats_commande[
'rows'] += $pFather->stats_commande[
'rows'];
2698 $this->stats_commande[
'qty'] += $pFather->stats_commande[
'qty'] * $qtyCoef;
2707 if (!empty($conf->global->STOCK_CALCULATE_ON_BILL)) {
2708 if (!empty($conf->global->DECREASE_ONLY_UNINVOICEDPRODUCTS)) {
2710 $sql =
"SELECT sum(fd.qty) as count FROM ".MAIN_DB_PREFIX.
"facturedet fd ";
2711 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"facture f ON fd.fk_facture = f.rowid ";
2712 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"element_element el ON el.fk_target = f.rowid and el.targettype = 'facture' and sourcetype = 'commande'";
2713 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"commande c ON el.fk_source = c.rowid ";
2714 $sql .=
" WHERE c.fk_statut IN (".$filtrestatut.
") AND c.facture = 0 AND fd.fk_product = ".$this->id;
2715 dol_syslog(__METHOD__.
":: sql $sql", LOG_NOTICE);
2719 if ($this->
db->num_rows(
$resql) > 0) {
2720 $obj = $this->
db->fetch_object(
$resql);
2721 $adeduire += $obj->count;
2725 $this->stats_commande[
'qty'] -= $adeduire;
2729 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
2730 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerOrder', $parameters, $this, $action);
2731 if ($reshook > 0) $this->stats_commande = $hookmanager->resArray[
'stats_commande'];
2734 $this->error = $this->
db->error();
2751 global $conf, $user, $hookmanager, $action;
2753 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_suppliers, COUNT(DISTINCT c.rowid) as nb,";
2754 $sql .=
" COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty";
2755 $sql .=
" FROM ".MAIN_DB_PREFIX.
"commande_fournisseurdet as cd";
2756 $sql .=
", ".MAIN_DB_PREFIX.
"commande_fournisseur as c";
2757 $sql .=
", ".MAIN_DB_PREFIX.
"societe as s";
2758 if (empty($user->rights->societe->client->voir) && !$socid && !$forVirtualStock) {
2759 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
2761 $sql .=
" WHERE c.rowid = cd.fk_commande";
2762 $sql .=
" AND c.fk_soc = s.rowid";
2763 $sql .=
" AND c.entity IN (".getEntity($forVirtualStock && !empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ?
'stock' :
'supplier_order').
")";
2764 $sql .=
" AND cd.fk_product = ".$this->id;
2765 if (empty($user->rights->societe->client->voir) && !$socid && !$forVirtualStock) {
2766 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
2769 $sql .=
" AND c.fk_soc = ".$socid;
2771 if ($filtrestatut !=
'') {
2772 $sql .=
" AND c.fk_statut in (".$this->db->sanitize($filtrestatut).
")";
2775 $result = $this->
db->query($sql);
2777 $obj = $this->
db->fetch_object($result);
2778 $this->stats_commande_fournisseur[
'suppliers'] = $obj->nb_suppliers;
2779 $this->stats_commande_fournisseur[
'nb'] = $obj->nb;
2780 $this->stats_commande_fournisseur[
'rows'] = $obj->nb_rows;
2781 $this->stats_commande_fournisseur[
'qty'] = $obj->qty ? $obj->qty : 0;
2783 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
2784 $reshook = $hookmanager->executeHooks(
'loadStatsSupplierOrder', $parameters, $this, $action);
2785 if ($reshook > 0) $this->stats_commande_fournisseur = $hookmanager->resArray[
'stats_commande_fournisseur'];
2789 $this->error = $this->
db->error().
' sql='.$sql;
2804 public function load_stats_sending($socid = 0, $filtrestatut =
'', $forVirtualStock = 0, $filterShipmentStatus =
'')
2807 global $conf, $user, $hookmanager;
2809 $sql =
"SELECT COUNT(DISTINCT e.fk_soc) as nb_customers, COUNT(DISTINCT e.rowid) as nb,";
2810 $sql .=
" COUNT(ed.rowid) as nb_rows, SUM(ed.qty) as qty";
2811 $sql .=
" FROM ".MAIN_DB_PREFIX.
"expeditiondet as ed";
2812 $sql .=
", ".MAIN_DB_PREFIX.
"commandedet as cd";
2813 $sql .=
", ".MAIN_DB_PREFIX.
"commande as c";
2814 $sql .=
", ".MAIN_DB_PREFIX.
"expedition as e";
2815 $sql .=
", ".MAIN_DB_PREFIX.
"societe as s";
2816 if (empty($user->rights->societe->client->voir) && !$socid && !$forVirtualStock) {
2817 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
2819 $sql .=
" WHERE e.rowid = ed.fk_expedition";
2820 $sql .=
" AND c.rowid = cd.fk_commande";
2821 $sql .=
" AND e.fk_soc = s.rowid";
2822 $sql .=
" AND e.entity IN (".getEntity($forVirtualStock && !empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ?
'stock' :
'expedition').
")";
2823 $sql .=
" AND ed.fk_origin_line = cd.rowid";
2824 $sql .=
" AND cd.fk_product = ".$this->id;
2825 if (empty($user->rights->societe->client->voir) && !$socid && !$forVirtualStock) {
2826 $sql .=
" AND e.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
2829 $sql .=
" AND e.fk_soc = ".$socid;
2831 if ($filtrestatut <>
'') {
2832 $sql .=
" AND c.fk_statut IN (".$this->db->sanitize($filtrestatut).
")";
2834 if (!empty($filterShipmentStatus)) $sql .=
" AND e.fk_statut IN (".$this->db->sanitize($filterShipmentStatus).
")";
2836 $result = $this->
db->query($sql);
2838 $obj = $this->
db->fetch_object($result);
2839 $this->stats_expedition[
'customers'] = $obj->nb_customers;
2840 $this->stats_expedition[
'nb'] = $obj->nb;
2841 $this->stats_expedition[
'rows'] = $obj->nb_rows;
2842 $this->stats_expedition[
'qty'] = $obj->qty ? $obj->qty : 0;
2845 if (!empty($conf->global->PRODUCT_STATS_WITH_PARENT_PROD_IF_INCDEC)) {
2847 if (is_array($TFather) && !empty($TFather)) {
2848 foreach ($TFather as &$fatherData) {
2850 $pFather->id = $fatherData[
'id'];
2851 $qtyCoef = $fatherData[
'qty'];
2853 if ($fatherData[
'incdec']) {
2854 $pFather->load_stats_sending($socid, $filtrestatut, $forVirtualStock);
2856 $this->stats_expedition[
'customers'] += $pFather->stats_expedition[
'customers'];
2857 $this->stats_expedition[
'nb'] += $pFather->stats_expedition[
'nb'];
2858 $this->stats_expedition[
'rows'] += $pFather->stats_expedition[
'rows'];
2859 $this->stats_expedition[
'qty'] += $pFather->stats_expedition[
'qty'] * $qtyCoef;
2865 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock,
'filterShipmentStatus' => $filterShipmentStatus);
2866 $reshook = $hookmanager->executeHooks(
'loadStatsSending', $parameters, $this, $action);
2867 if ($reshook > 0) $this->stats_expedition = $hookmanager->resArray[
'stats_expedition'];
2871 $this->error = $this->
db->error();
2888 global $conf, $user, $hookmanager, $action;
2890 $sql =
"SELECT COUNT(DISTINCT cf.fk_soc) as nb_suppliers, COUNT(DISTINCT cf.rowid) as nb,";
2891 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(fd.qty) as qty";
2892 $sql .=
" FROM ".MAIN_DB_PREFIX.
"commande_fournisseur_dispatch as fd";
2893 $sql .=
", ".MAIN_DB_PREFIX.
"commande_fournisseur as cf";
2894 $sql .=
", ".MAIN_DB_PREFIX.
"societe as s";
2895 if (empty($user->rights->societe->client->voir) && !$socid && !$forVirtualStock) {
2896 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
2898 $sql .=
" WHERE cf.rowid = fd.fk_commande";
2899 $sql .=
" AND cf.fk_soc = s.rowid";
2900 $sql .=
" AND cf.entity IN (".getEntity($forVirtualStock && !empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ?
'stock' :
'supplier_order').
")";
2901 $sql .=
" AND fd.fk_product = ".$this->id;
2902 if (empty($user->rights->societe->client->voir) && !$socid && !$forVirtualStock) {
2903 $sql .=
" AND cf.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
2906 $sql .=
" AND cf.fk_soc = ".$socid;
2908 if ($filtrestatut <>
'') {
2909 $sql .=
" AND cf.fk_statut IN (".$this->db->sanitize($filtrestatut).
")";
2912 $result = $this->
db->query($sql);
2914 $obj = $this->
db->fetch_object($result);
2915 $this->stats_reception[
'suppliers'] = $obj->nb_suppliers;
2916 $this->stats_reception[
'nb'] = $obj->nb;
2917 $this->stats_reception[
'rows'] = $obj->nb_rows;
2918 $this->stats_reception[
'qty'] = $obj->qty ? $obj->qty : 0;
2920 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
2921 $reshook = $hookmanager->executeHooks(
'loadStatsReception', $parameters, $this, $action);
2922 if ($reshook > 0) $this->stats_reception = $hookmanager->resArray[
'stats_reception'];
2926 $this->error = $this->
db->error();
2943 global $conf, $user, $hookmanager;
2945 $sql =
"SELECT COUNT(DISTINCT m.fk_soc) as nb_customers, COUNT(DISTINCT m.rowid) as nb,";
2946 $sql .=
" COUNT(mp.rowid) as nb_rows, SUM(mp.qty) as qty, role";
2947 $sql .=
" FROM ".MAIN_DB_PREFIX.
"mrp_production as mp";
2948 $sql .=
", ".MAIN_DB_PREFIX.
"mrp_mo as m";
2949 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s ON s.rowid = m.fk_soc";
2950 if (empty($user->rights->societe->client->voir) && !$socid && !$forVirtualStock) {
2951 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
2953 $sql .=
" WHERE m.rowid = mp.fk_mo";
2954 $sql .=
" AND m.entity IN (".getEntity($forVirtualStock && !empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ?
'stock' :
'mrp').
")";
2955 $sql .=
" AND mp.fk_product = ".$this->id;
2956 if (empty($user->rights->societe->client->voir) && !$socid && !$forVirtualStock) {
2957 $sql .=
" AND m.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
2960 $sql .=
" AND m.fk_soc = ".$socid;
2962 if ($filtrestatut <>
'') {
2963 $sql .=
" AND m.status IN (".$this->db->sanitize($filtrestatut).
")";
2965 $sql .=
" GROUP BY role";
2967 $this->stats_mrptoconsume[
'customers'] = 0;
2968 $this->stats_mrptoconsume[
'nb'] = 0;
2969 $this->stats_mrptoconsume[
'rows'] = 0;
2970 $this->stats_mrptoconsume[
'qty'] = 0;
2971 $this->stats_mrptoproduce[
'customers'] = 0;
2972 $this->stats_mrptoproduce[
'nb'] = 0;
2973 $this->stats_mrptoproduce[
'rows'] = 0;
2974 $this->stats_mrptoproduce[
'qty'] = 0;
2976 $result = $this->
db->query($sql);
2978 while ($obj = $this->
db->fetch_object($result)) {
2979 if ($obj->role ==
'toconsume') {
2980 $this->stats_mrptoconsume[
'customers'] += $obj->nb_customers;
2981 $this->stats_mrptoconsume[
'nb'] += $obj->nb;
2982 $this->stats_mrptoconsume[
'rows'] += $obj->nb_rows;
2983 $this->stats_mrptoconsume[
'qty'] += ($obj->qty ? $obj->qty : 0);
2985 if ($obj->role ==
'consumed') {
2989 $this->stats_mrptoconsume[
'qty'] -= ($obj->qty ? $obj->qty : 0);
2991 if ($obj->role ==
'toproduce') {
2992 $this->stats_mrptoproduce[
'customers'] += $obj->nb_customers;
2993 $this->stats_mrptoproduce[
'nb'] += $obj->nb;
2994 $this->stats_mrptoproduce[
'rows'] += $obj->nb_rows;
2995 $this->stats_mrptoproduce[
'qty'] += ($obj->qty ? $obj->qty : 0);
2997 if ($obj->role ==
'produced') {
3001 $this->stats_mrptoproduce[
'qty'] -= ($obj->qty ? $obj->qty : 0);
3006 if ($this->stats_mrptoconsume[
'qty'] < 0) $this->stats_mrptoconsume[
'qty'] = 0;
3007 if ($this->stats_mrptoproduce[
'qty'] < 0) $this->stats_mrptoproduce[
'qty'] = 0;
3009 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3010 $reshook = $hookmanager->executeHooks(
'loadStatsInProduction', $parameters, $this, $action);
3011 if ($reshook > 0) $this->stats_mrptoproduce = $hookmanager->resArray[
'stats_mrptoproduce'];
3015 $this->error = $this->
db->error();
3030 global $conf, $user, $hookmanager;
3032 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,";
3033 $sql .=
" COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty";
3034 $sql .=
" FROM ".MAIN_DB_PREFIX.
"contratdet as cd";
3035 $sql .=
", ".MAIN_DB_PREFIX.
"contrat as c";
3036 $sql .=
", ".MAIN_DB_PREFIX.
"societe as s";
3037 if (empty($user->rights->societe->client->voir) && !$socid) {
3038 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
3040 $sql .=
" WHERE c.rowid = cd.fk_contrat";
3041 $sql .=
" AND c.fk_soc = s.rowid";
3042 $sql .=
" AND c.entity IN (".getEntity(
'contract').
")";
3043 $sql .=
" AND cd.fk_product = ".$this->id;
3044 if (empty($user->rights->societe->client->voir) && !$socid) {
3045 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
3049 $sql .=
" AND c.fk_soc = ".$socid;
3052 $result = $this->
db->query($sql);
3054 $obj = $this->
db->fetch_object($result);
3055 $this->stats_contrat[
'customers'] = $obj->nb_customers;
3056 $this->stats_contrat[
'nb'] = $obj->nb;
3057 $this->stats_contrat[
'rows'] = $obj->nb_rows;
3058 $this->stats_contrat[
'qty'] = $obj->qty ? $obj->qty : 0;
3061 if (!empty($conf->global->PRODUCT_STATS_WITH_PARENT_PROD_IF_INCDEC)) {
3063 if (is_array($TFather) && !empty($TFather)) {
3064 foreach ($TFather as &$fatherData) {
3066 $pFather->id = $fatherData[
'id'];
3067 $qtyCoef = $fatherData[
'qty'];
3069 if ($fatherData[
'incdec']) {
3070 $pFather->load_stats_contrat($socid);
3072 $this->stats_contrat[
'customers'] += $pFather->stats_contrat[
'customers'];
3073 $this->stats_contrat[
'nb'] += $pFather->stats_contrat[
'nb'];
3074 $this->stats_contrat[
'rows'] += $pFather->stats_contrat[
'rows'];
3075 $this->stats_contrat[
'qty'] += $pFather->stats_contrat[
'qty'] * $qtyCoef;
3081 $parameters = array(
'socid' => $socid);
3082 $reshook = $hookmanager->executeHooks(
'loadStatsContract', $parameters, $this, $action);
3083 if ($reshook > 0) $this->stats_contrat = $hookmanager->resArray[
'stats_contrat'];
3087 $this->error = $this->
db->error().
' sql='.$sql;
3102 global $db, $conf, $user, $hookmanager;
3104 $sql =
"SELECT COUNT(DISTINCT f.fk_soc) as nb_customers, COUNT(DISTINCT f.rowid) as nb,";
3105 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(".$this->db->ifsql(
'f.type != 2',
'fd.qty',
'fd.qty * -1').
") as qty";
3106 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facturedet as fd";
3107 $sql .=
", ".MAIN_DB_PREFIX.
"facture as f";
3108 $sql .=
", ".MAIN_DB_PREFIX.
"societe as s";
3109 if (empty($user->rights->societe->client->voir) && !$socid) {
3110 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
3112 $sql .=
" WHERE f.rowid = fd.fk_facture";
3113 $sql .=
" AND f.fk_soc = s.rowid";
3114 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
3115 $sql .=
" AND fd.fk_product = ".$this->id;
3116 if (empty($user->rights->societe->client->voir) && !$socid) {
3117 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
3121 $sql .=
" AND f.fk_soc = ".$socid;
3124 $result = $this->
db->query($sql);
3126 $obj = $this->
db->fetch_object($result);
3127 $this->stats_facture[
'customers'] = $obj->nb_customers;
3128 $this->stats_facture[
'nb'] = $obj->nb;
3129 $this->stats_facture[
'rows'] = $obj->nb_rows;
3130 $this->stats_facture[
'qty'] = $obj->qty ? $obj->qty : 0;
3133 if (!empty($conf->global->PRODUCT_STATS_WITH_PARENT_PROD_IF_INCDEC)) {
3135 if (is_array($TFather) && !empty($TFather)) {
3136 foreach ($TFather as &$fatherData) {
3138 $pFather->id = $fatherData[
'id'];
3139 $qtyCoef = $fatherData[
'qty'];
3141 if ($fatherData[
'incdec']) {
3142 $pFather->load_stats_facture($socid);
3144 $this->stats_facture[
'customers'] += $pFather->stats_facture[
'customers'];
3145 $this->stats_facture[
'nb'] += $pFather->stats_facture[
'nb'];
3146 $this->stats_facture[
'rows'] += $pFather->stats_facture[
'rows'];
3147 $this->stats_facture[
'qty'] += $pFather->stats_facture[
'qty'] * $qtyCoef;
3153 $parameters = array(
'socid' => $socid);
3154 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerInvoice', $parameters, $this, $action);
3155 if ($reshook > 0) $this->stats_facture = $hookmanager->resArray[
'stats_facture'];
3159 $this->error = $this->
db->error();
3174 global $conf, $user, $hookmanager, $action;
3176 $sql =
"SELECT COUNT(DISTINCT f.fk_soc) as nb_suppliers, COUNT(DISTINCT f.rowid) as nb,";
3177 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(fd.qty) as qty";
3178 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture_fourn_det as fd";
3179 $sql .=
", ".MAIN_DB_PREFIX.
"facture_fourn as f";
3180 $sql .=
", ".MAIN_DB_PREFIX.
"societe as s";
3181 if (empty($user->rights->societe->client->voir) && !$socid) {
3182 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
3184 $sql .=
" WHERE f.rowid = fd.fk_facture_fourn";
3185 $sql .=
" AND f.fk_soc = s.rowid";
3186 $sql .=
" AND f.entity IN (".getEntity(
'facture_fourn').
")";
3187 $sql .=
" AND fd.fk_product = ".$this->id;
3188 if (empty($user->rights->societe->client->voir) && !$socid) {
3189 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
3193 $sql .=
" AND f.fk_soc = ".$socid;
3196 $result = $this->
db->query($sql);
3198 $obj = $this->
db->fetch_object($result);
3199 $this->stats_facture_fournisseur[
'suppliers'] = $obj->nb_suppliers;
3200 $this->stats_facture_fournisseur[
'nb'] = $obj->nb;
3201 $this->stats_facture_fournisseur[
'rows'] = $obj->nb_rows;
3202 $this->stats_facture_fournisseur[
'qty'] = $obj->qty ? $obj->qty : 0;
3204 $parameters = array(
'socid' => $socid);
3205 $reshook = $hookmanager->executeHooks(
'loadStatsSupplierInvoice', $parameters, $this, $action);
3206 if ($reshook > 0) $this->stats_facture_fournisseur = $hookmanager->resArray[
'stats_facture_fournisseur'];
3210 $this->error = $this->
db->error();
3231 $num = $this->
db->num_rows(
$resql);
3235 $arr = $this->
db->fetch_array(
$resql);
3236 $keyfortab = (string) $arr[1];
3238 $keyfortab = substr($keyfortab, -2);
3241 if ($mode ==
'byunit') {
3242 $tab[$keyfortab] = (empty($tab[$keyfortab]) ? 0 : $tab[$keyfortab]) + $arr[0];
3243 } elseif ($mode ==
'bynumber') {
3244 $tab[$keyfortab] = (empty($tab[$keyfortab]) ? 0 : $tab[$keyfortab]) + $arr[2];
3249 $this->error = $this->
db->error().
' sql='.$sql;
3254 $year = strftime(
'%Y', time());
3255 $month = strftime(
'%m', time());
3256 } elseif ($year == -1) {
3265 for ($j = 0; $j < 12; $j++)
3268 $idx = ucfirst(
dol_trunc(
dol_print_date(
dol_mktime(12, 0, 0, $month, 1, 1970),
"%b"), 1,
'right',
'UTF-8', 1));
3271 $result[$j] = array($idx, isset($tab[$year.$month]) ? $tab[$year.$month] : 0);
3274 $month =
"0".($month - 1);
3276 $month = substr($month, 1);
3284 return array_reverse($result);
3299 public function get_nb_vente($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
3305 $sql =
"SELECT sum(d.qty), date_format(f.datef, '%Y%m')";
3306 if ($mode ==
'bynumber') {
3307 $sql .=
", count(DISTINCT f.rowid)";
3309 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facturedet as d, ".MAIN_DB_PREFIX.
"facture as f, ".MAIN_DB_PREFIX.
"societe as s";
3310 if ($filteronproducttype >= 0) {
3311 $sql .=
", ".MAIN_DB_PREFIX.
"product as p";
3313 if (empty($user->rights->societe->client->voir) && !$socid) {
3314 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
3316 $sql .=
" WHERE f.rowid = d.fk_facture";
3317 if ($this->
id > 0) {
3318 $sql .=
" AND d.fk_product =".$this->id;
3320 $sql .=
" AND d.fk_product > 0";
3322 if ($filteronproducttype >= 0) {
3323 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
3325 $sql .=
" AND f.fk_soc = s.rowid";
3326 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
3327 if (empty($user->rights->societe->client->voir) && !$socid) {
3328 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
3331 $sql .=
" AND f.fk_soc = $socid";
3333 $sql .= $morefilter;
3334 $sql .=
" GROUP BY date_format(f.datef,'%Y%m')";
3335 $sql .=
" ORDER BY date_format(f.datef,'%Y%m') DESC";
3337 return $this->
_get_stats($sql, $mode, $year);
3352 public function get_nb_achat($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
3358 $sql =
"SELECT sum(d.qty), date_format(f.datef, '%Y%m')";
3359 if ($mode ==
'bynumber') {
3360 $sql .=
", count(DISTINCT f.rowid)";
3362 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture_fourn_det as d, ".MAIN_DB_PREFIX.
"facture_fourn as f, ".MAIN_DB_PREFIX.
"societe as s";
3363 if ($filteronproducttype >= 0) {
3364 $sql .=
", ".MAIN_DB_PREFIX.
"product as p";
3366 if (empty($user->rights->societe->client->voir) && !$socid) {
3367 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
3369 $sql .=
" WHERE f.rowid = d.fk_facture_fourn";
3370 if ($this->
id > 0) {
3371 $sql .=
" AND d.fk_product =".$this->id;
3373 $sql .=
" AND d.fk_product > 0";
3375 if ($filteronproducttype >= 0) {
3376 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
3378 $sql .=
" AND f.fk_soc = s.rowid";
3379 $sql .=
" AND f.entity IN (".getEntity(
'facture_fourn').
")";
3380 if (empty($user->rights->societe->client->voir) && !$socid) {
3381 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
3384 $sql .=
" AND f.fk_soc = $socid";
3386 $sql .= $morefilter;
3387 $sql .=
" GROUP BY date_format(f.datef,'%Y%m')";
3388 $sql .=
" ORDER BY date_format(f.datef,'%Y%m') DESC";
3390 return $this->
_get_stats($sql, $mode, $year);
3404 public function get_nb_propal($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
3407 global $conf, $user;
3409 $sql =
"SELECT sum(d.qty), date_format(p.datep, '%Y%m')";
3410 if ($mode ==
'bynumber') {
3411 $sql .=
", count(DISTINCT p.rowid)";
3413 $sql .=
" FROM ".MAIN_DB_PREFIX.
"propaldet as d, ".MAIN_DB_PREFIX.
"propal as p, ".MAIN_DB_PREFIX.
"societe as s";
3414 if ($filteronproducttype >= 0) {
3415 $sql .=
", ".MAIN_DB_PREFIX.
"product as prod";
3417 if (empty($user->rights->societe->client->voir) && !$socid) {
3418 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
3420 $sql .=
" WHERE p.rowid = d.fk_propal";
3421 if ($this->
id > 0) {
3422 $sql .=
" AND d.fk_product =".$this->id;
3424 $sql .=
" AND d.fk_product > 0";
3426 if ($filteronproducttype >= 0) {
3427 $sql .=
" AND prod.rowid = d.fk_product AND prod.fk_product_type = ".((int) $filteronproducttype);
3429 $sql .=
" AND p.fk_soc = s.rowid";
3430 $sql .=
" AND p.entity IN (".getEntity(
'propal').
")";
3431 if (empty($user->rights->societe->client->voir) && !$socid) {
3432 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
3435 $sql .=
" AND p.fk_soc = ".$socid;
3437 $sql .= $morefilter;
3438 $sql .=
" GROUP BY date_format(p.datep,'%Y%m')";
3439 $sql .=
" ORDER BY date_format(p.datep,'%Y%m') DESC";
3441 return $this->
_get_stats($sql, $mode, $year);
3461 $sql =
"SELECT sum(d.qty), date_format(p.date_valid, '%Y%m')";
3462 if ($mode ==
'bynumber') {
3463 $sql .=
", count(DISTINCT p.rowid)";
3465 $sql .=
" FROM ".MAIN_DB_PREFIX.
"supplier_proposaldet as d, ".MAIN_DB_PREFIX.
"supplier_proposal as p, ".MAIN_DB_PREFIX.
"societe as s";
3466 if ($filteronproducttype >= 0) {
3467 $sql .=
", ".MAIN_DB_PREFIX.
"product as prod";
3469 if (empty($user->rights->societe->client->voir) && !$socid) {
3470 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
3472 $sql .=
" WHERE p.rowid = d.fk_supplier_proposal";
3473 if ($this->
id > 0) {
3474 $sql .=
" AND d.fk_product =".$this->id;
3476 $sql .=
" AND d.fk_product > 0";
3478 if ($filteronproducttype >= 0) {
3479 $sql .=
" AND prod.rowid = d.fk_product AND prod.fk_product_type = ".((int) $filteronproducttype);
3481 $sql .=
" AND p.fk_soc = s.rowid";
3482 $sql .=
" AND p.entity IN (".getEntity(
'supplier_proposal').
")";
3483 if (empty($user->rights->societe->client->voir) && !$socid) {
3484 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
3487 $sql .=
" AND p.fk_soc = ".$socid;
3489 $sql .= $morefilter;
3490 $sql .=
" GROUP BY date_format(p.date_valid,'%Y%m')";
3491 $sql .=
" ORDER BY date_format(p.date_valid,'%Y%m') DESC";
3493 return $this->
_get_stats($sql, $mode, $year);
3507 public function get_nb_order($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
3510 global $conf, $user;
3512 $sql =
"SELECT sum(d.qty), date_format(c.date_commande, '%Y%m')";
3513 if ($mode ==
'bynumber') {
3514 $sql .=
", count(DISTINCT c.rowid)";
3516 $sql .=
" FROM ".MAIN_DB_PREFIX.
"commandedet as d, ".MAIN_DB_PREFIX.
"commande as c, ".MAIN_DB_PREFIX.
"societe as s";
3517 if ($filteronproducttype >= 0) {
3518 $sql .=
", ".MAIN_DB_PREFIX.
"product as p";
3520 if (empty($user->rights->societe->client->voir) && !$socid) {
3521 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
3523 $sql .=
" WHERE c.rowid = d.fk_commande";
3524 if ($this->
id > 0) {
3525 $sql .=
" AND d.fk_product =".$this->id;
3527 $sql .=
" AND d.fk_product > 0";
3529 if ($filteronproducttype >= 0) {
3530 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
3532 $sql .=
" AND c.fk_soc = s.rowid";
3533 $sql .=
" AND c.entity IN (".getEntity(
'commande').
")";
3534 if (empty($user->rights->societe->client->voir) && !$socid) {
3535 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
3538 $sql .=
" AND c.fk_soc = ".$socid;
3540 $sql .= $morefilter;
3541 $sql .=
" GROUP BY date_format(c.date_commande,'%Y%m')";
3542 $sql .=
" ORDER BY date_format(c.date_commande,'%Y%m') DESC";
3544 return $this->
_get_stats($sql, $mode, $year);
3561 global $conf, $user;
3563 $sql =
"SELECT sum(d.qty), date_format(c.date_commande, '%Y%m')";
3564 if ($mode ==
'bynumber') {
3565 $sql .=
", count(DISTINCT c.rowid)";
3567 $sql .=
" FROM ".MAIN_DB_PREFIX.
"commande_fournisseurdet as d, ".MAIN_DB_PREFIX.
"commande_fournisseur as c, ".MAIN_DB_PREFIX.
"societe as s";
3568 if ($filteronproducttype >= 0) {
3569 $sql .=
", ".MAIN_DB_PREFIX.
"product as p";
3571 if (empty($user->rights->societe->client->voir) && !$socid) {
3572 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
3574 $sql .=
" WHERE c.rowid = d.fk_commande";
3575 if ($this->
id > 0) {
3576 $sql .=
" AND d.fk_product =".$this->id;
3578 $sql .=
" AND d.fk_product > 0";
3580 if ($filteronproducttype >= 0) {
3581 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
3583 $sql .=
" AND c.fk_soc = s.rowid";
3584 $sql .=
" AND c.entity IN (".getEntity(
'supplier_order').
")";
3585 if (empty($user->rights->societe->client->voir) && !$socid) {
3586 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
3589 $sql .=
" AND c.fk_soc = ".$socid;
3591 $sql .= $morefilter;
3592 $sql .=
" GROUP BY date_format(c.date_commande,'%Y%m')";
3593 $sql .=
" ORDER BY date_format(c.date_commande,'%Y%m') DESC";
3595 return $this->
_get_stats($sql, $mode, $year);
3609 public function get_nb_contract($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
3612 global $conf, $user;
3614 $sql =
"SELECT sum(d.qty), date_format(c.date_contrat, '%Y%m')";
3615 if ($mode ==
'bynumber') {
3616 $sql .=
", count(DISTINCT c.rowid)";
3618 $sql .=
" FROM ".MAIN_DB_PREFIX.
"contratdet as d, ".MAIN_DB_PREFIX.
"contrat as c, ".MAIN_DB_PREFIX.
"societe as s";
3619 if ($filteronproducttype >= 0) {
3620 $sql .=
", ".MAIN_DB_PREFIX.
"product as p";
3622 if (empty($user->rights->societe->client->voir) && !$socid) {
3623 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
3626 $sql .=
" WHERE c.entity IN (".getEntity(
'contract').
")";
3627 $sql .=
" AND c.rowid = d.fk_contrat";
3629 if ($this->
id > 0) {
3630 $sql .=
" AND d.fk_product =".$this->id;
3632 $sql .=
" AND d.fk_product > 0";
3634 if ($filteronproducttype >= 0) {
3635 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
3637 $sql .=
" AND c.fk_soc = s.rowid";
3639 if (empty($user->rights->societe->client->voir) && !$socid) {
3640 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
3643 $sql .=
" AND c.fk_soc = ".$socid;
3645 $sql .= $morefilter;
3646 $sql .=
" GROUP BY date_format(c.date_contrat,'%Y%m')";
3647 $sql .=
" ORDER BY date_format(c.date_contrat,'%Y%m') DESC";
3649 return $this->
_get_stats($sql, $mode, $year);
3663 public function get_nb_mos($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
3666 global $conf, $user;
3668 $sql =
"SELECT sum(d.qty), date_format(d.date_valid, '%Y%m')";
3669 if ($mode ==
'bynumber') {
3670 $sql .=
", count(DISTINCT d.rowid)";
3672 $sql .=
" FROM ".MAIN_DB_PREFIX.
"mrp_mo as d LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s ON d.fk_soc = s.rowid";
3673 if ($filteronproducttype >= 0) {
3674 $sql .=
", ".MAIN_DB_PREFIX.
"product as p";
3676 if (empty($user->rights->societe->client->voir) && !$socid) {
3677 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
3680 $sql .=
" WHERE d.entity IN (".getEntity(
'mo').
")";
3681 $sql .=
" AND d.status > 0";
3683 if ($this->
id > 0) {
3684 $sql .=
" AND d.fk_product =".$this->id;
3686 $sql .=
" AND d.fk_product > 0";
3688 if ($filteronproducttype >= 0) {
3689 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
3692 if (empty($user->rights->societe->client->voir) && !$socid) {
3693 $sql .=
" AND d.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
3696 $sql .=
" AND d.fk_soc = ".$socid;
3698 $sql .= $morefilter;
3699 $sql .=
" GROUP BY date_format(d.date_valid,'%Y%m')";
3700 $sql .=
" ORDER BY date_format(d.date_valid,'%Y%m') DESC";
3702 return $this->
_get_stats($sql, $mode, $year);
3719 if (!is_numeric($id_pere)) {
3722 if (!is_numeric($id_fils)) {
3725 if (!is_numeric($incdec)) {
3735 $sql =
'SELECT fk_product_pere from '.MAIN_DB_PREFIX.
'product_association';
3736 $sql .=
' WHERE fk_product_pere = '.$id_fils.
' AND fk_product_fils = '.$id_pere;
3737 if (!$this->
db->query($sql)) {
3741 $result = $this->
db->query($sql);
3743 $num = $this->
db->num_rows($result);
3745 $this->error =
"isFatherOfThis";
3748 $sql =
'INSERT INTO '.MAIN_DB_PREFIX.
'product_association(fk_product_pere,fk_product_fils,qty,incdec)';
3749 $sql .=
' VALUES ('.$id_pere.
', '.$id_fils.
', '.$qty.
', '.$incdec.
')';
3750 if (!$this->
db->query($sql)) {
3775 if (!is_numeric($id_pere)) {
3778 if (!is_numeric($id_fils)) {
3781 if (!is_numeric($incdec)) {
3784 if (!is_numeric($qty)) {
3788 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'product_association SET ';
3789 $sql .=
'qty='.$qty;
3790 $sql .=
',incdec='.$incdec;
3791 $sql .=
' WHERE fk_product_pere='.$id_pere.
' AND fk_product_fils='.$id_fils;
3793 if (!$this->
db->query($sql)) {
3812 if (!is_numeric($fk_parent)) {
3815 if (!is_numeric($fk_child)) {
3819 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"product_association";
3820 $sql .=
" WHERE fk_product_pere = ".$fk_parent;
3821 $sql .=
" AND fk_product_fils = ".$fk_child;
3823 dol_syslog(get_class($this).
'::del_sousproduit', LOG_DEBUG);
3824 if (!$this->
db->query($sql)) {
3843 $sql =
"SELECT fk_product_pere, qty, incdec";
3844 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product_association";
3845 $sql .=
" WHERE fk_product_pere = ".((int) $fk_parent);
3846 $sql .=
" AND fk_product_fils = ".((int) $fk_child);
3848 $result = $this->
db->query($sql);
3850 $num = $this->
db->num_rows($result);
3853 $obj = $this->
db->fetch_object($result);
3855 $this->is_sousproduit_qty = $obj->qty;
3856 $this->is_sousproduit_incdec = $obj->incdec;
3887 dol_syslog(get_class($this).
"::add_fournisseur id_fourn = ".$id_fourn.
" ref_fourn=".
$ref_fourn.
" quantity=".$quantity, LOG_DEBUG);
3893 $sql =
"SELECT rowid, fk_product";
3894 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product_fournisseur_price";
3895 $sql .=
" WHERE fk_soc = ".((int) $id_fourn);
3896 $sql .=
" AND ref_fourn = '".$this->db->escape(
$ref_fourn).
"'";
3897 $sql .=
" AND fk_product <> ".((int) $this->
id);
3898 $sql .=
" AND entity IN (".getEntity(
'productsupplierprice').
")";
3902 $obj = $this->
db->fetch_object(
$resql);
3905 $this->product_id_already_linked = $obj->fk_product;
3912 $sql =
"SELECT rowid";
3913 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product_fournisseur_price";
3914 $sql .=
" WHERE fk_soc = ".$id_fourn;
3916 }
else { $sql .=
" AND (ref_fourn = '' OR ref_fourn IS NULL)";
3918 $sql .=
" AND quantity = ".$quantity;
3919 $sql .=
" AND fk_product = ".$this->id;
3920 $sql .=
" AND entity IN (".getEntity(
'productsupplierprice').
")";
3924 $obj = $this->
db->fetch_object(
$resql);
3928 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"product_fournisseur_price(";
3931 $sql .=
", fk_product";
3933 $sql .=
", ref_fourn";
3934 $sql .=
", quantity";
3935 $sql .=
", fk_user";
3937 $sql .=
") VALUES (";
3938 $sql .=
"'".$this->db->idate($now).
"'";
3939 $sql .=
", ".$conf->entity;
3940 $sql .=
", ".$this->id;
3941 $sql .=
", ".$id_fourn;
3942 $sql .=
", '".$this->db->escape(
$ref_fourn).
"'";
3943 $sql .=
", ".$quantity;
3944 $sql .=
", ".$user->id;
3948 if ($this->
db->query($sql)) {
3949 $this->product_fourn_price_id = $this->
db->last_insert_id(MAIN_DB_PREFIX.
"product_fournisseur_price");
3952 $this->error = $this->
db->lasterror();
3957 $this->product_fourn_price_id = $obj->rowid;
3961 $this->error = $this->
db->lasterror();
3980 $sql =
"SELECT DISTINCT p.fk_soc";
3981 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product_fournisseur_price as p";
3982 $sql .=
" WHERE p.fk_product = ".$this->id;
3983 $sql .=
" AND p.entity = ".$conf->entity;
3985 $result = $this->
db->query($sql);
3987 $num = $this->
db->num_rows($result);
3991 $obj = $this->
db->fetch_object($result);
3992 $list[$i] = $obj->fk_soc;
4010 global $conf, $user;
4017 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"product_price (";
4019 $sql .=
", fk_product";
4020 $sql .=
", date_price";
4021 $sql .=
", price_level";
4023 $sql .=
", price_ttc";
4024 $sql .=
", price_min";
4025 $sql .=
", price_min_ttc";
4026 $sql .=
", price_base_type";
4027 $sql .=
", default_vat_code";
4029 $sql .=
", recuperableonly";
4030 $sql .=
", localtax1_tx";
4031 $sql .=
", localtax1_type";
4032 $sql .=
", localtax2_tx";
4033 $sql .=
", localtax2_type";
4034 $sql .=
", fk_user_author";
4036 $sql .=
", price_by_qty";
4037 $sql .=
", fk_price_expression";
4038 $sql .=
", fk_multicurrency";
4039 $sql .=
", multicurrency_code";
4040 $sql .=
", multicurrency_tx";
4041 $sql .=
", multicurrency_price";
4042 $sql .=
", multicurrency_price_ttc";
4047 $sql .=
", '".$this->db->idate($now).
"'";
4048 $sql .=
", price_level";
4050 $sql .=
", price_ttc";
4051 $sql .=
", price_min";
4052 $sql .=
", price_min_ttc";
4053 $sql .=
", price_base_type";
4054 $sql .=
", default_vat_code";
4056 $sql .=
", recuperableonly";
4057 $sql .=
", localtax1_tx";
4058 $sql .=
", localtax1_type";
4059 $sql .=
", localtax2_tx";
4060 $sql .=
", localtax2_type";
4061 $sql .=
", ".$user->id;
4063 $sql .=
", price_by_qty";
4064 $sql .=
", fk_price_expression";
4065 $sql .=
", fk_multicurrency";
4066 $sql .=
", multicurrency_code";
4067 $sql .=
", multicurrency_tx";
4068 $sql .=
", multicurrency_price";
4069 $sql .=
", multicurrency_price_ttc";
4070 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product_price";
4071 $sql .=
" WHERE fk_product = ".$fromId;
4072 $sql .=
" ORDER BY date_price DESC";
4073 if ($conf->global->PRODUIT_MULTIPRICES_LIMIT > 0) {
4074 $sql .=
" LIMIT ".$conf->global->PRODUIT_MULTIPRICES_LIMIT;
4080 $this->
db->rollback();
4084 $this->
db->commit();
4101 $sql =
'INSERT INTO '.MAIN_DB_PREFIX.
'product_association (fk_product_pere, fk_product_fils, qty)';
4102 $sql .=
" SELECT ".$toId.
", fk_product_fils, qty FROM ".MAIN_DB_PREFIX.
"product_association";
4103 $sql .=
" WHERE fk_product_pere = ".$fromId;
4105 dol_syslog(get_class($this).
'::clone_association', LOG_DEBUG);
4106 if (!$this->
db->query($sql)) {
4107 $this->
db->rollback();
4111 $this->
db->commit();
4144 $sql =
"INSERT ".MAIN_DB_PREFIX.
"product_fournisseur_price (";
4145 $sql .=
" datec, fk_product, fk_soc, price, quantity, fk_user)";
4146 $sql .=
" SELECT '".$this->db->idate($now).
"', ".$toId.
", fk_soc, price, quantity, fk_user";
4147 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product_fournisseur_price";
4148 $sql .=
" WHERE fk_product = ".$fromId;
4150 dol_syslog(get_class($this).
'::clone_fournisseurs', LOG_DEBUG);
4153 $this->
db->rollback();
4156 $this->
db->commit();
4173 public function fetch_prod_arbo($prod, $compl_path =
"", $multiply = 1, $level = 1, $id_parent = 0)
4176 global $conf, $langs;
4180 foreach ($prod as $id_product => $desc_pere)
4182 if (is_array($desc_pere))
4184 $id = (!empty($desc_pere[0]) ? $desc_pere[0] :
'');
4185 $nb = (!empty($desc_pere[1]) ? $desc_pere[1] :
'');
4186 $type = (!empty($desc_pere[2]) ? $desc_pere[2] :
'');
4187 $label = (!empty($desc_pere[3]) ? $desc_pere[3] :
'');
4188 $incdec = !empty($desc_pere[4]) ? $desc_pere[4] : 0;
4190 if ($multiply < 1) { $multiply = 1;
4194 if (is_null($tmpproduct)) $tmpproduct =
new Product($this->
db);
4195 $tmpproduct->fetch($id);
4196 $tmpproduct->load_stock(
'nobatch,novirtual');
4199 $this->res[] = array(
4201 'id_parent'=>$id_parent,
4202 'ref'=>$tmpproduct->ref,
4204 'nb_total'=>$nb * $multiply,
4205 'stock'=>$tmpproduct->stock_reel,
4206 'stock_alert'=>$tmpproduct->seuil_stock_alerte,
4208 'fullpath'=>$compl_path.$label,
4210 'desiredstock'=>$tmpproduct->desiredstock,
4213 'entity'=>$tmpproduct->entity
4217 if (is_array($desc_pere[
'childs'])) {
4219 $this->
fetch_prod_arbo($desc_pere[
'childs'], $compl_path.$desc_pere[3].
" -> ", $desc_pere[1] * $multiply, $level + 1, $id);
4236 $this->res = array();
4237 if (isset($this->sousprods) && is_array($this->sousprods)) {
4238 foreach ($this->sousprods as $prod_name => $desc_product) {
4239 if (is_array($desc_product)) {
4259 $sql =
"SELECT COUNT(pa.rowid) as nb";
4260 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product_association as pa";
4262 $sql .=
" WHERE pa.fk_product_fils = ".$this->id.
" OR pa.fk_product_pere = ".$this->id;
4263 } elseif ($mode == -1) {
4264 $sql .=
" WHERE pa.fk_product_fils = ".$this->id;
4265 } elseif ($mode == 1) {
4266 $sql .=
" WHERE pa.fk_product_pere = ".$this->id;
4271 $obj = $this->
db->fetch_object(
$resql);
4272 if ($obj) { $nb = $obj->nb; }
4288 $sql =
"SELECT count(rowid) as nb FROM ".MAIN_DB_PREFIX.
"product_attribute_combination WHERE fk_product_parent = ".$this->id;
4289 $sql .=
" AND entity IN (".getEntity(
'product').
")";
4293 $obj = $this->
db->fetch_object(
$resql);
4294 if ($obj) { $nb = $obj->nb;
4310 if (!empty($conf->variants->enabled)) {
4311 $sql =
"SELECT rowid FROM ".MAIN_DB_PREFIX.
"product_attribute_combination WHERE fk_product_child = ".$this->
id.
" AND entity IN (".
getEntity(
'product').
")";
4313 $query = $this->
db->query($sql);
4316 if (!$this->
db->num_rows($query)) {
4337 $sql =
"SELECT p.rowid, p.label as label, p.ref as ref, pa.fk_product_pere as id, p.fk_product_type, pa.qty, pa.incdec, p.entity";
4338 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product_association as pa,";
4339 $sql .=
" ".MAIN_DB_PREFIX.
"product as p";
4340 $sql .=
" WHERE p.rowid = pa.fk_product_pere";
4341 $sql .=
" AND pa.fk_product_fils = ".$this->id;
4343 $res = $this->
db->query($sql);
4346 while ($record = $this->
db->fetch_array($res))
4349 $prods[$record[
'id']][
'id'] = $record[
'rowid'];
4350 $prods[$record[
'id']][
'ref'] = $record[
'ref'];
4351 $prods[$record[
'id']][
'label'] = $record[
'label'];
4352 $prods[$record[
'id']][
'qty'] = $record[
'qty'];
4353 $prods[$record[
'id']][
'incdec'] = $record[
'incdec'];
4354 $prods[$record[
'id']][
'fk_product_type'] = $record[
'fk_product_type'];
4355 $prods[$record[
'id']][
'entity'] = $record[
'entity'];
4375 global $alreadyfound;
4381 $sql =
"SELECT p.rowid, p.ref, p.label as label, p.fk_product_type,";
4382 $sql .=
" pa.qty as qty, pa.fk_product_fils as id, pa.incdec";
4383 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product as p,";
4384 $sql .=
" ".MAIN_DB_PREFIX.
"product_association as pa";
4385 $sql .=
" WHERE p.rowid = pa.fk_product_fils";
4386 $sql .=
" AND pa.fk_product_pere = ".$id;
4387 $sql .=
" AND pa.fk_product_fils != ".$id;
4389 dol_syslog(get_class($this).
'::getChildsArbo id='.$id.
' level='.$level, LOG_DEBUG);
4391 if ($level == 1) { $alreadyfound = array($id=>1);
4398 $res = $this->
db->query($sql);
4401 while ($rec = $this->
db->fetch_array($res))
4403 if (!empty($alreadyfound[$rec[
'rowid']])) {
4404 dol_syslog(get_class($this).
'::getChildsArbo the product id='.$rec[
'rowid'].
' was already found at a higher level in tree. We discard to avoid infinite loop', LOG_WARNING);
4407 $alreadyfound[$rec[
'rowid']] = 1;
4408 $prods[$rec[
'rowid']] = array(
4411 2=>$rec[
'fk_product_type'],
4412 3=>$this->
db->escape($rec[
'label']),
4418 if (empty($firstlevelonly)) {
4419 $listofchilds = $this->
getChildsArbo($rec[
'rowid'], 0, $level + 1);
4420 foreach ($listofchilds as $keyChild => $valueChild)
4422 $prods[$rec[
'rowid']][
'childs'][$keyChild] = $valueChild;
4446 foreach ($this->
getChildsArbo($this->
id) as $keyChild => $valueChild)
4448 $parent[$this->label][$keyChild] = $valueChild;
4450 foreach ($parent as $key => $value)
4452 $this->sousprods[$key] = $value;
4466 public function getNomUrl($withpicto = 0, $option =
'', $maxlength = 0, $save_lastsearch_value = -1, $notooltip = 0)
4468 global $conf, $langs, $hookmanager;
4469 include_once DOL_DOCUMENT_ROOT.
'/core/lib/product.lib.php';
4471 $result =
''; $label =
'';
4473 $newref = $this->ref;
4475 $newref =
dol_trunc($newref, $maxlength,
'middle');
4478 if (!empty($this->entity)) {
4479 $tmpphoto = $this->
show_photos(
'product', $conf->product->multidir_output[$this->entity], 1, 1, 0, 0, 0, 80);
4480 if ($this->nbphoto > 0) {
4481 $label .=
'<div class="photointooltip">';
4482 $label .= $tmpphoto;
4483 $label .=
'</div><div style="clear: both;"></div>';
4488 $label .=
img_picto(
'',
'product').
' <u class="paddingrightonly">'.$langs->trans(
"Product").
'</u>';
4490 $label .=
img_picto(
'',
'service').
' <u class="paddingrightonly">'.$langs->trans(
"Service").
'</u>';
4492 if (isset($this->status) && isset($this->status_buy)) {
4493 $label .=
' '.$this->getLibStatut(5, 0);
4494 $label .=
' '.$this->getLibStatut(5, 1);
4497 if (!empty($this->ref)) {
4498 $label .=
'<br><b>'.$langs->trans(
'ProductRef').
':</b> '.$this->ref;
4500 if (!empty($this->label)) {
4501 $label .=
'<br><b>'.$langs->trans(
'ProductLabel').
':</b> '.$this->label;
4504 if (!empty($conf->productbatch->enabled)) {
4505 $langs->load(
"productbatch");
4506 $label .=
"<br><b>".$langs->trans(
"ManageLotSerial").
'</b>: '.$this->
getLibStatut(0, 2);
4509 if (!empty($conf->barcode->enabled)) {
4510 $label .=
'<br><b>'.$langs->trans(
'BarCode').
':</b> '.$this->barcode;
4515 if ($this->weight) {
4516 $label .=
"<br><b>".$langs->trans(
"Weight").
'</b>: '.$this->weight.
' '.
measuringUnitString(0,
"weight", $this->weight_units);
4519 if ($this->length) {
4520 $labelsize .= ($labelsize ?
" - " :
"").
"<b>".$langs->trans(
"Length").
'</b>: '.$this->length.
' '.
measuringUnitString(0,
'size', $this->length_units);
4523 $labelsize .= ($labelsize ?
" - " :
"").
"<b>".$langs->trans(
"Width").
'</b>: '.$this->width.
' '.
measuringUnitString(0,
'size', $this->width_units);
4525 if ($this->height) {
4526 $labelsize .= ($labelsize ?
" - " :
"").
"<b>".$langs->trans(
"Height").
'</b>: '.$this->height.
' '.
measuringUnitString(0,
'size', $this->height_units);
4528 if ($labelsize) $label .=
"<br>".$labelsize;
4530 $labelsurfacevolume =
"";
4531 if ($this->surface) {
4532 $labelsurfacevolume .= ($labelsurfacevolume ?
" - " :
"").
"<b>".$langs->trans(
"Surface").
'</b>: '.$this->surface.
' '.
measuringUnitString(0,
'surface', $this->surface_units);
4534 if ($this->volume) {
4535 $labelsurfacevolume .= ($labelsurfacevolume ?
" - " :
"").
"<b>".$langs->trans(
"Volume").
'</b>: '.$this->volume.
' '.
measuringUnitString(0,
'volume', $this->volume_units);
4537 if ($labelsurfacevolume) $label .=
"<br>".$labelsurfacevolume;
4540 if (!empty($conf->accounting->enabled) && $this->status) {
4541 include_once DOL_DOCUMENT_ROOT.
'/core/lib/accounting.lib.php';
4542 $label .=
'<br><b>'.$langs->trans(
'ProductAccountancySellCode').
':</b> '.
length_accountg($this->accountancy_code_sell);
4543 $label .=
'<br><b>'.$langs->trans(
'ProductAccountancySellIntraCode').
':</b> '.
length_accountg($this->accountancy_code_sell_intra);
4544 $label .=
'<br><b>'.$langs->trans(
'ProductAccountancySellExportCode').
':</b> '.
length_accountg($this->accountancy_code_sell_export);
4546 if (!empty($conf->accounting->enabled) && $this->status_buy) {
4547 include_once DOL_DOCUMENT_ROOT.
'/core/lib/accounting.lib.php';
4548 $label .=
'<br><b>'.$langs->trans(
'ProductAccountancyBuyCode').
':</b> '.
length_accountg($this->accountancy_code_buy);
4549 $label .=
'<br><b>'.$langs->trans(
'ProductAccountancyBuyIntraCode').
':</b> '.
length_accountg($this->accountancy_code_buy_intra);
4550 $label .=
'<br><b>'.$langs->trans(
'ProductAccountancyBuyExportCode').
':</b> '.
length_accountg($this->accountancy_code_buy_export);
4554 if (empty($notooltip)) {
4555 if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
4556 $label = $langs->trans(
"ShowProduct");
4557 $linkclose .=
' alt="'.dol_escape_htmltag($label, 1).
'"';
4560 $linkclose .=
' title="'.dol_escape_htmltag($label, 1, 1).
'"';
4561 $linkclose .=
' class="nowraponall classfortooltip"';
4563 $linkclose =
' class="nowraponall"';
4566 if ($option ==
'supplier' || $option ==
'category') {
4567 $url = DOL_URL_ROOT.
'/product/fournisseurs.php?id='.$this->id;
4568 } elseif ($option ==
'stock') {
4569 $url = DOL_URL_ROOT.
'/product/stock/product.php?id='.$this->id;
4570 } elseif ($option ==
'composition') {
4571 $url = DOL_URL_ROOT.
'/product/composition/card.php?id='.$this->id;
4573 $url = DOL_URL_ROOT.
'/product/card.php?id='.$this->id;
4576 if ($option !==
'nolink') {
4578 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
4579 if ($save_lastsearch_value == -1 && preg_match(
'/list\.php/',
$_SERVER[
"PHP_SELF"])) { $add_save_lastsearch_values = 1;
4581 if ($add_save_lastsearch_values) { $url .=
'&save_lastsearch_values=1';
4585 $linkstart =
'<a href="'.$url.
'"';
4586 $linkstart .= $linkclose.
'>';
4589 $result .= $linkstart;
4593 $result .= (
img_object(($notooltip ?
'' : $label),
'product', ($notooltip ?
'class="paddingright"' :
'class="paddingright classfortooltip"'), 0, 0, $notooltip ? 0 : 1));
4596 $result .= (
img_object(($notooltip ?
'' : $label),
'service', ($notooltip ?
'class="paddinright"' :
'class="paddingright classfortooltip"'), 0, 0, $notooltip ? 0 : 1));
4600 $result .= $linkend;
4603 $hookmanager->initHooks(array(
'productdao'));
4604 $parameters = array(
'id'=>$this->
id,
'getnomurl'=>$result);
4605 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
4607 $result = $hookmanager->resPrint;
4609 $result .= $hookmanager->resPrint;
4626 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
4628 global $conf, $user, $langs;
4630 $langs->load(
"products");
4631 $outputlangs->load(
"products");
4635 if (!empty($conf->global->PRODUCT_ADDON_PDF)) {
4636 $modele = $conf->global->PRODUCT_ADDON_PDF;
4642 $modelpath =
"core/modules/product/doc/";
4644 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
4659 return $this->
LibStatut($this->status, $mode, $type);
4661 return $this->
LibStatut($this->status_buy, $mode, $type);
4663 return $this->
LibStatut($this->status_batch, $mode, $type);
4666 return $this->
LibStatut($this->status_buy, $mode, $type);
4682 global $conf, $langs;
4684 $labelStatus = $labelStatusShort =
'';
4686 $langs->load(
'products');
4687 if (!empty($conf->productbatch->enabled)) { $langs->load(
"productbatch");
4694 $label = ($status == 0 ? $langs->trans(
'ProductStatusNotOnBatch') : $langs->trans(
'ProductStatusOnBatch'));
4697 $label = ($status == 0 ? $langs->trans(
'ProductStatusNotOnBatchShort') : $langs->trans(
'ProductStatusOnBatchShort'));
4702 return dolGetStatus($langs->trans(
'ProductStatusNotOnBatch'),
'',
'', empty($status) ?
'status5' :
'status4', 3,
'dot');
4712 $statuttrans = empty($status) ?
'status5' :
'status4';
4717 $labelStatus = $langs->trans(
'ProductStatusNotOnSellShort');
4718 $labelStatusShort = $langs->trans(
'ProductStatusNotOnSell');
4719 } elseif ($type == 1) {
4720 $labelStatus = $langs->trans(
'ProductStatusNotOnBuyShort');
4721 $labelStatusShort = $langs->trans(
'ProductStatusNotOnBuy');
4722 } elseif ($type == 2) {
4723 $labelStatus = $langs->trans(
'ProductStatusNotOnBatch');
4724 $labelStatusShort = $langs->trans(
'ProductStatusNotOnBatchShort');
4726 } elseif ($status == 1) {
4729 $labelStatus = $langs->trans(
'ProductStatusOnSellShort');
4730 $labelStatusShort = $langs->trans(
'ProductStatusOnSell');
4731 } elseif ($type == 1) {
4732 $labelStatus = $langs->trans(
'ProductStatusOnBuyShort');
4733 $labelStatusShort = $langs->trans(
'ProductStatusOnBuy');
4734 } elseif ($type == 2) {
4735 $labelStatus = $langs->trans(
'ProductStatusOnBatch');
4736 $labelStatusShort = $langs->trans(
'ProductStatusOnBatchShort');
4742 return dolGetStatus($langs->trans(
'Unknown'),
'',
'',
'status0', 0);
4744 return dolGetStatus($labelStatus, $labelStatusShort,
'', $statuttrans, $mode);
4757 $langs->load(
'products');
4759 if (isset($this->finished) && $this->finished >= 0) {
4760 $sql =
'SELECT label, code FROM '.MAIN_DB_PREFIX.
'c_product_nature where code='.((int) $this->finished).
' AND active=1';
4763 $res = $this->
db->fetch_array(
$resql);
4764 $label = $langs->trans($res[
'label']);
4768 $this->error = $this->
db->error().
' sql='.$sql;
4769 dol_syslog(__METHOD__.
' Error '.$this->error, LOG_ERR);
4794 public function correct_stock($user, $id_entrepot, $nbpiece, $movement, $label =
'', $price = 0, $inventorycode =
'', $origin_element =
'', $origin_id = null, $disablestockchangeforsubproduct = 0)
4800 include_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
4802 $op[0] =
"+".trim($nbpiece);
4803 $op[1] =
"-".trim($nbpiece);
4806 $movementstock->setOrigin($origin_element, $origin_id);
4807 $result = $movementstock->_create($user, $this->
id, $id_entrepot, $op[$movement], $movement, $price, $label, $inventorycode,
'',
'',
'',
'',
false, 0, $disablestockchangeforsubproduct);
4810 $this->
db->commit();
4813 $this->error = $movementstock->error;
4814 $this->errors = $movementstock->errors;
4816 $this->
db->rollback();
4841 public function correct_stock_batch($user, $id_entrepot, $nbpiece, $movement, $label =
'', $price = 0, $dlc =
'', $dluo =
'', $lot =
'', $inventorycode =
'', $origin_element =
'', $origin_id = null, $disablestockchangeforsubproduct = 0)
4847 include_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
4849 $op[0] =
"+".trim($nbpiece);
4850 $op[1] =
"-".trim($nbpiece);
4853 $movementstock->setOrigin($origin_element, $origin_id);
4854 $result = $movementstock->_create($user, $this->
id, $id_entrepot, $op[$movement], $movement, $price, $label, $inventorycode,
'', $dlc, $dluo, $lot,
false, 0, $disablestockchangeforsubproduct);
4857 $this->
db->commit();
4860 $this->error = $movementstock->error;
4861 $this->errors = $movementstock->errors;
4863 $this->
db->rollback();
4880 public function load_stock($option =
'', $includedraftpoforvirtual = null)
4885 $this->stock_reel = 0;
4886 $this->stock_warehouse = array();
4887 $this->stock_theorique = 0;
4889 $warehouseStatus = array();
4891 if (preg_match(
'/warehouseclosed/', $option)) {
4894 if (preg_match(
'/warehouseopen/', $option)) {
4897 if (preg_match(
'/warehouseinternal/', $option)) {
4901 $sql =
"SELECT ps.rowid, ps.reel, ps.fk_entrepot";
4902 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product_stock as ps";
4903 $sql .=
", ".MAIN_DB_PREFIX.
"entrepot as w";
4904 $sql .=
" WHERE w.entity IN (".getEntity(
'stock').
")";
4905 $sql .=
" AND w.rowid = ps.fk_entrepot";
4906 $sql .=
" AND ps.fk_product = ".$this->id;
4907 if (!empty($conf->global->ENTREPOT_EXTRA_STATUS) && count($warehouseStatus)) {
4908 $sql .=
" AND w.statut IN (".$this->db->sanitize($this->
db->escape(implode(
',', $warehouseStatus))).
")";
4911 dol_syslog(get_class($this).
"::load_stock", LOG_DEBUG);
4912 $result = $this->
db->query($sql);
4914 $num = $this->
db->num_rows($result);
4919 $row = $this->
db->fetch_object($result);
4920 $this->stock_warehouse[$row->fk_entrepot] =
new stdClass();
4921 $this->stock_warehouse[$row->fk_entrepot]->real = $row->reel;
4922 $this->stock_warehouse[$row->fk_entrepot]->id = $row->rowid;
4923 if ((!preg_match(
'/nobatch/', $option)) && $this->
hasbatch()) {
4924 $this->stock_warehouse[$row->fk_entrepot]->detail_batch =
Productbatch::findAll($this->
db, $row->rowid, 1, $this->id);
4926 $this->stock_reel += $row->reel;
4930 $this->
db->free($result);
4932 if (!preg_match(
'/novirtual/', $option)) {
4938 $this->error = $this->
db->lasterror();
4956 global $conf, $hookmanager, $action;
4958 $stock_commande_client = 0;
4959 $stock_commande_fournisseur = 0;
4960 $stock_sending_client = 0;
4961 $stock_reception_fournisseur = 0;
4962 $stock_inproduction = 0;
4966 if (!empty($conf->commande->enabled))
4970 $stock_commande_client = $this->stats_commande[
'qty'];
4972 if (!empty($conf->expedition->enabled))
4974 require_once DOL_DOCUMENT_ROOT.
'/expedition/class/expedition.class.php';
4975 $filterShipmentStatus =
'';
4976 if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT)) {
4978 } elseif (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE)) {
4983 $stock_sending_client = $this->stats_expedition[
'qty'];
4985 if (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled))
4987 $filterStatus =
'1,2,3,4';
4988 if (isset($includedraftpoforvirtual)) $filterStatus =
'0,'.$filterStatus;
4991 $stock_commande_fournisseur = $this->stats_commande_fournisseur[
'qty'];
4993 if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && empty($conf->reception->enabled))
4995 $filterStatus =
'4';
4996 if (isset($includedraftpoforvirtual)) $filterStatus =
'0,'.$filterStatus;
4999 $stock_reception_fournisseur = $this->stats_reception[
'qty'];
5001 if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && empty($conf->reception->enabled))
5003 $filterStatus =
'4';
5004 if (isset($includedraftpoforvirtual)) $filterStatus =
'0,'.$filterStatus;
5007 $stock_reception_fournisseur = $this->stats_reception[
'qty'];
5009 if (!empty($conf->mrp->enabled))
5013 $stock_inproduction = $this->stats_mrptoproduce[
'qty'] - $this->stats_mrptoconsume[
'qty'];
5016 $this->stock_theorique = $this->stock_reel + $stock_inproduction;
5019 if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT) || !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE)) {
5020 $this->stock_theorique -= ($stock_commande_client - $stock_sending_client);
5021 } elseif (!empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER)) {
5022 $this->stock_theorique += 0;
5023 } elseif (!empty($conf->global->STOCK_CALCULATE_ON_BILL)) {
5024 $this->stock_theorique -= $stock_commande_client;
5027 if (!empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE)) {
5028 $this->stock_theorique += ($stock_commande_fournisseur - $stock_reception_fournisseur);
5029 } elseif (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER)) {
5030 $this->stock_theorique += ($stock_commande_fournisseur - $stock_reception_fournisseur);
5031 } elseif (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER)) {
5032 $this->stock_theorique -= $stock_reception_fournisseur;
5033 } elseif (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_BILL)) {
5034 $this->stock_theorique += ($stock_commande_fournisseur - $stock_reception_fournisseur);
5037 if (!is_object($hookmanager)) {
5038 include_once DOL_DOCUMENT_ROOT.
'/core/class/hookmanager.class.php';
5041 $hookmanager->initHooks(array(
'productdao'));
5042 $parameters = array(
'id'=>$this->
id,
'includedraftpoforvirtual' => $includedraftpoforvirtual);
5044 $reshook = $hookmanager->executeHooks(
'loadvirtualstock', $parameters, $this, $action);
5045 if ($reshook > 0) $this->stock_theorique = $hookmanager->resArray[
'stock_theorique'];
5062 $sql =
"SELECT pb.batch, pb.eatby, pb.sellby, SUM(pb.qty) AS qty FROM ".MAIN_DB_PREFIX.
"product_batch as pb, ".MAIN_DB_PREFIX.
"product_stock as ps";
5063 $sql .=
" WHERE pb.fk_product_stock = ps.rowid AND ps.fk_product = ".$this->id.
" AND pb.batch = '".$this->
db->escape($batch).
"'";
5064 $sql .=
" GROUP BY pb.batch, pb.eatby, pb.sellby";
5065 dol_syslog(get_class($this).
"::loadBatchInfo load first entry found for lot/serial = ".$batch, LOG_DEBUG);
5068 $num = $this->
db->num_rows(
$resql);
5072 $obj = $this->
db->fetch_object(
$resql);
5073 $result[] = array(
'batch'=>$batch,
'eatby'=>$this->
db->jdate($obj->eatby),
'sellby'=>$this->
db->jdate($obj->sellby),
'qty'=>$obj->qty);
5079 $this->
db->rollback();
5097 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
5102 if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) {
5103 $dir .=
'/'.get_exdir($this->
id, 2, 0, 0, $this,
'product').$this->id.
"/photos";
5105 $dir .=
'/'.get_exdir(0, 0, 0, 0, $this,
'product').dol_sanitizeFileName($this->ref);
5110 $dir_osencoded = $dir;
5112 if (is_dir($dir_osencoded)) {
5113 $originImage = $dir.
'/'.$file[
'name'];
5124 if (is_numeric($result) && $result > 0) {
5141 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
5142 include_once DOL_DOCUMENT_ROOT.
'/core/lib/images.lib.php';
5147 if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) {
5148 $dir .=
'/'.get_exdir($this->
id, 2, 0, 0, $this,
'product').$this->id.
"/photos/";
5150 $dir .=
'/'.get_exdir(0, 0, 0, 0, $this,
'product');
5156 if (file_exists($dir_osencoded)) {
5157 $handle = opendir($dir_osencoded);
5158 if (is_resource($handle)) {
5159 while (($file = readdir($handle)) !==
false)
5162 $file = utf8_encode($file);
5184 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
5185 include_once DOL_DOCUMENT_ROOT.
'/core/lib/images.lib.php';
5191 $handle = @opendir($dir_osencoded);
5192 if (is_resource($handle)) {
5193 while (($file = readdir($handle)) !==
false)
5195 if (!
utf8_check($file)) { $file = utf8_encode($file);
5202 $photo_vignette =
'';
5203 if (preg_match(
'/('.$this->regeximgext.
')$/i', $photo, $regs)) {
5204 $photo_vignette = preg_replace(
'/'.$regs[0].
'/i',
'', $photo).
'_small'.$regs[0];
5207 $dirthumb = $dir.
'thumbs/';
5211 $obj[
'photo'] = $photo;
5212 if ($photo_vignette &&
dol_is_file($dirthumb.$photo_vignette)) { $obj[
'photo_vignette'] =
'thumbs/'.$photo_vignette;
5213 }
else { $obj[
'photo_vignette'] =
"";
5216 $tabobj[$nbphoto - 1] = $obj;
5219 if ($nbmax && $nbphoto >= $nbmax) {
break;
5240 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
5241 include_once DOL_DOCUMENT_ROOT.
'/core/lib/images.lib.php';
5243 $dir = dirname($file).
'/';
5244 $dirthumb = $dir.
'/thumbs/';
5245 $filename = preg_replace(
'/'.preg_quote($dir,
'/').
'/i',
'', $file);
5251 if (preg_match(
'/('.$this->regeximgext.
')$/i', $filename, $regs)) {
5252 $photo_vignette = preg_replace(
'/'.$regs[0].
'/i',
'', $filename).
'_small'.$regs[0];
5253 if (file_exists(
dol_osencode($dirthumb.$photo_vignette))) {
5257 $photo_vignette = preg_replace(
'/'.$regs[0].
'/i',
'', $filename).
'_mini'.$regs[0];
5258 if (file_exists(
dol_osencode($dirthumb.$photo_vignette))) {
5275 $infoImg = getimagesize($file_osencoded);
5276 $this->imgWidth = $infoImg[0];
5277 $this->imgHeight = $infoImg[1];
5289 global $conf, $user, $hookmanager;
5291 $this->nb = array();
5293 $sql =
"SELECT count(p.rowid) as nb, fk_product_type";
5294 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product as p";
5295 $sql .=
' WHERE p.entity IN ('.getEntity($this->element, 1).
')';
5297 if (is_object($hookmanager)) {
5298 $parameters = array();
5299 $reshook = $hookmanager->executeHooks(
'printFieldListWhere', $parameters);
5300 $sql .= $hookmanager->resPrint;
5302 $sql .=
' GROUP BY fk_product_type';
5306 while ($obj = $this->
db->fetch_object(
$resql))
5308 if ($obj->fk_product_type == 1) { $this->nb[
"services"] = $obj->nb;
5309 }
else { $this->nb[
"products"] = $obj->nb;
5316 $this->error = $this->
db->error();
5356 if (!empty($conf->global->BARCODE_PRODUCT_ADDON_NUM)) {
5357 $dirsociete = array_merge(array(
'/core/modules/barcode/'), $conf->modules_parts[
'barcode']);
5358 foreach ($dirsociete as $dirroot)
5360 $res =
dol_include_once($dirroot.$conf->global->BARCODE_PRODUCT_ADDON_NUM.
'.php');
5364 $var = $conf->global->BARCODE_PRODUCT_ADDON_NUM;
5367 $result = $mod->getNextValue($object, $type);
5369 dol_syslog(get_class($this).
"::get_barcode barcode=".$result.
" module=".$var);
5383 global $user, $langs, $conf, $mysoc;
5388 $this->specimen = 1;
5390 $this->ref =
'PRODUCT_SPEC';
5391 $this->label =
'PRODUCT SPECIMEN';
5392 $this->
description =
'This is description of this product specimen that was created the '.dol_print_date($now,
'dayhourlog').
'.';
5393 $this->specimen = 1;
5394 $this->country_id = 1;
5398 $this->
note =
'This is a comment (private)';
5399 $this->date_creation = $now;
5400 $this->date_modification = $now;
5403 $this->weight_units = 3;
5406 $this->length_units = 1;
5408 $this->width_units = 0;
5409 $this->height = null;
5410 $this->height_units = null;
5412 $this->surface = 30;
5413 $this->surface_units = 0;
5414 $this->volume = 300;
5415 $this->volume_units = 0;
5417 $this->barcode = -1;
5430 if (!$this->fk_unit) {
5434 $langs->load(
'products');
5436 $label_type =
'label';
5437 if ($type ==
'short') {
5438 $label_type =
'short_label';
5441 $sql =
'select '.$label_type.
', code from '.MAIN_DB_PREFIX.
'c_units where rowid='.$this->fk_unit;
5444 $res = $this->
db->fetch_array(
$resql);
5445 $label = ($label_type ==
'short_label' ? $res[$label_type] :
'unit'.$res[
'code']);
5449 $this->error = $this->
db->error().
' sql='.$sql;
5450 dol_syslog(get_class($this).
"::getLabelOfUnit Error ".$this->error, LOG_ERR);
5462 return ($this->status_batch == 1 ?
true :
false);
5477 $maxpricesupplier = 0;
5479 if (!empty($conf->global->PRODUCT_MINIMUM_RECOMMENDED_PRICE)) {
5480 include_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
5482 $product_fourn_list = $product_fourn->list_product_fournisseur_price($this->
id,
'',
'');
5484 if (is_array($product_fourn_list) && count($product_fourn_list) > 0) {
5485 foreach ($product_fourn_list as $productfourn)
5487 if ($productfourn->fourn_unitprice > $maxpricesupplier) {
5488 $maxpricesupplier = $productfourn->fourn_unitprice;
5492 $maxpricesupplier *= $conf->global->PRODUCT_MINIMUM_RECOMMENDED_PRICE;
5496 return $maxpricesupplier;
5513 if (!is_array($categories)) {
5514 $categories = array($categories);
5518 include_once DOL_DOCUMENT_ROOT.
'/categories/class/categorie.class.php';
5520 $existing = $c->containing($this->
id, Categorie::TYPE_PRODUCT,
'id');
5523 if (is_array($existing)) {
5524 $to_del = array_diff($existing, $categories);
5525 $to_add = array_diff($categories, $existing);
5528 $to_add = $categories;
5532 foreach ($to_del as $del) {
5533 if ($c->fetch($del) > 0) {
5534 $c->del_type($this, Categorie::TYPE_PRODUCT);
5537 foreach ($to_add as $add) {
5538 if ($c->fetch($add) > 0) {
5539 $c->add_type($this, Categorie::TYPE_PRODUCT);
5557 'product_customer_price',
5558 'product_customer_price_log'
5579 $sql =
"SELECT rowid, level, fk_level, var_percent, var_min_percent FROM ".MAIN_DB_PREFIX.
"product_pricerules";
5580 $query = $this->
db->query($sql);
5584 while ($result = $this->
db->fetch_object($query)) {
5585 $rules[$result->level] = $result;
5593 for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++) {
5594 $price = $baseprice;
5595 $price_min = $baseprice;
5599 if ($i > 1 && isset($rules[$i]->var_percent) && $rules[$i]->var_percent) {
5600 $price = $prices[$rules[$i]->fk_level] * (1 + ($rules[$i]->var_percent / 100));
5603 $prices[$i] = $price;
5606 if (isset($rules[$i]->var_min_percent) && $rules[$i]->var_min_percent) {
5607 $price_min = $price * (1 - ($rules[$i]->var_min_percent / 100));
5611 $check_amount = (($price == $this->multiprices[$i]) && ($price_min == $this->multiprices_min[$i]));
5612 $check_type = ($baseprice == $this->multiprices_base_type[$i]);
5614 if ($check_amount && $check_type) {
5618 if ($this->
updatePrice($price, $price_type, $user, $price_vat, $price_min, $i, $npr, $psq,
true) < 0) {
5636 return $user->rights->produit;
5638 return $user->rights->service;
5650 $sql =
"SELECT p.rowid, p.ref, p.datec as date_creation, p.tms as date_modification,";
5651 $sql .=
" p.fk_user_author, p.fk_user_modif";
5652 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as p";
5653 $sql .=
" WHERE p.rowid = ".$id;
5655 $result = $this->
db->query($sql);
5657 if ($this->
db->num_rows($result)) {
5658 $obj = $this->
db->fetch_object($result);
5660 $this->
id = $obj->rowid;
5662 if ($obj->fk_user_author) {
5663 $cuser =
new User($this->
db);
5664 $cuser->fetch($obj->fk_user_author);
5665 $this->user_creation = $cuser;
5668 if ($obj->fk_user_modif) {
5669 $muser =
new User($this->
db);
5670 $muser->fetch($obj->fk_user_modif);
5671 $this->user_modification = $muser;
5674 $this->ref = $obj->ref;
5675 $this->date_creation = $this->
db->jdate($obj->date_creation);
5676 $this->date_modification = $this->
db->jdate($obj->date_modification);
5679 $this->
db->free($result);
5694 public $picto =
'service';
if(!function_exists('dol_getprefix')) dol_include_once($relpath, $classname= '')
Make an include_once using default root and alternate root if it fails.
is_sousproduit($fk_parent, $fk_child)
Check if it is a sub-product into a kit.
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
File of class to manage predefined price products or services by customer.
update_sousproduit($id_pere, $id_fils, $qty, $incdec=1)
Modify composed product.
load_stats_inproduction($socid=0, $filtrestatut= '', $forVirtualStock=0)
Charge tableau des stats production pour le produit/service.
$multiprices
Arrays for multiprices.
hasVariants()
Return if a product has variants or not.
Class to manage stock movements.
getLibFinished()
Retour label of nature of product.
get_nb_contract($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter= '')
Return nb of units in orders in which product is included.
load_stats_facture_fournisseur($socid=0)
Charge tableau des stats facture pour le produit/service.
get_nb_vente($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter= '')
Return nb of units or customers invoices in which product is included.
getRights()
Returns the rights used for this class.
const STATUS_CLOSED
Warehouse closed, inactive.
create($user, $notrigger=0)
Insert product into database.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm= 'auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
Class to parse product price expressions.
addThumbs($file)
Build thumb.
get_nb_achat($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter= '')
Return nb of units or supplier invoices in which product is included.
load_stats_commande($socid=0, $filtrestatut= '', $forVirtualStock=0)
Charge tableau des stats commande client pour le produit/service.
const STATUS_OPEN_ALL
Warehouse open and operations for customer shipping, supplier dispatch, internal stock transfers/corr...
static replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
isVariant()
Return if loaded product is a variant.
setPriceExpression($expression_id)
Sets the supplier price expression.
</td > param sortfield sortorder printFieldListOption< tdclass="liste_titremaxwidthsearchright"></td ></tr >< trclass="liste_titre">< inputtype="checkbox"onClick="toggle(this)"/> Ref p ref Label p label Duration p duration center DesiredStock p desiredstock right StockLimitShort p seuil_stock_alerte right stock_physique right stock_real_warehouse right Ordered right StockToBuy right SupplierRef right param sortfield sortorder printFieldListTitle warehouseinternal SELECT description FROM product_lang WHERE qty< br > qty qty qty StockTooLow StockTooLow help help help< trclass="oddeven">< td >< inputtype="checkbox"class="check"name="choose'.$i.'"></td >< tdclass="nowrap"> stock</td >< td >< inputtype="hidden"name="desc'.$i.'"value="'.dol_escape_htmltag($objp-> description
Only used if Module[ID]Desc translation string is not found.
load_stats_propale($socid=0)
Charge tableau des stats propale pour le produit/service.
isObjectUsed($id=0)
Function to check if an object is used by others.
get_barcode($object, $type= '')
Get a barcode from the module to generate barcode values.
correct_stock($user, $id_entrepot, $nbpiece, $movement, $label= '', $price=0, $inventorycode= '', $origin_element= '', $origin_id=null, $disablestockchangeforsubproduct=0)
Adjust stock in a warehouse for product.
$duration_unit
Exoiration unit.
loadBatchInfo($batch)
Load existing information about a serial.
$product_fourn_id
Id du fournisseur.
Class to manage products or services.
dol_now($mode= 'auto')
Return date for now.
const TYPE_ASSEMBLYKIT
Advanced feature: assembly kit.
verify()
Check properties of product are ok (like name, barcode, ...).
getChildsArbo($id, $firstlevelonly=0, $level=1)
Return childs of product $id.
Class to manage Dolibarr users.
load_stats_commande_fournisseur($socid=0, $filtrestatut= '', $forVirtualStock=0)
Charge tableau des stats commande fournisseur pour le produit/service.
const TYPE_STOCKKIT
Advanced feature: stock kit.
Class to manage Dolibarr database access.
$weight
Metric of products.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
setMultiLangs($user)
Update or add a translation for a product.
isProduct()
Return if object is a product.
clone_price($fromId, $toId)
Recopie les prix d'un produit/service sur un autre.
const TYPE_SERVICE
Service.
getFather()
Return all parent products for current product (first level only)
$product_id_already_linked
Product ID already linked to a reference supplier.
Class to manage products or services.
load_stats_sending($socid=0, $filtrestatut= '', $forVirtualStock=0, $filterShipmentStatus= '')
Charge tableau des stats expedition client pour le produit/service.
updatePrice($newprice, $newpricebase, $user, $newvat= '', $newminprice=0, $level=0, $newnpr=0, $newpbq=0, $ignore_autogen=0, $localtaxes_array=array(), $newdefaultvatcode= '')
Modify customer price of a product/Service.
LibStatut($status, $mode=0, $type=0)
Return label of a given status.
const TYPE_PRODUCT
Regular product.
info($id)
Load information for tab info.
is_photo_available($sdir)
Return if at least one photo is available.
get_default_npr(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Fonction qui renvoie si tva doit etre tva percue recuperable.
liste_photos($dir, $nbmax=0)
Retourne tableau de toutes les photos du produit.
get_localtax($vatrate, $local, $thirdparty_buyer="", $thirdparty_seller="", $vatnpr=0)
Return localtax rate for a particular vat, when selling a product with vat $vatrate, from a $thirdparty_buyer to a $thirdparty_seller Note: This function applies same rules than get_default_tva.
del_sousproduit($fk_parent, $fk_child)
Retire le lien entre un sousproduit et un produit/service.
get_arbo_each_prod($multiply=1)
Build the tree of subproducts into an array this->sousprods is loaded by this->get_sousproduits_arbo(...
clone_fournisseurs($fromId, $toId)
Recopie les fournisseurs et prix fournisseurs d'un produit/service sur un autre.
const STATUS_CLOSED
Closed status.
$conf db
API class for accounts.
image_format_supported($file, $acceptsvg=0)
Return if a filename is file name of a supported image format.
$desiredstock
Ask for replenishment when $desiredstock < $stock_reel.
$localtax1_tx
Other local taxes.
load_stats_facture($socid=0)
Charge tableau des stats facture pour le produit/service.
price($amount, $form=0, $outlangs= '', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code= '')
Function to format a value into an amount for visual output Function used into PDF and HTML pages...
$default_vat_code
Default VAT code for product (link to code into llx_c_tva but without foreign keys) ...
getLabelOfUnit($type= 'long')
Returns the text label from units dictionary.
$price_by_qty
Price by quantity arrays.
insertExtraFields($trigger= '', $userused=null)
Add/Update all extra fields values for the current object.
initAsSpecimen()
Initialise an instance with random values.
dol_string_nospecial($str, $newstr= '_', $badcharstoreplace= '')
Clean a string from all punctuation characters to use it as a ref or login.
list_suppliers()
Return list of suppliers providing the product or service.
$tva_tx
Default VAT rate of product.
$stock_warehouse
Contains detail of stock of product into each warehouse.
add_sousproduit($id_pere, $id_fils, $qty, $incdec=1)
Link a product/service to a parent product/service.
load_stats_bom($socid=0)
Charge tableau des stats OF pour le produit/service.
load_stock($option= '', $includedraftpoforvirtual=null)
Load information about stock of a product into ->stock_reel, ->stock_warehouse[] (including stock_war...
add_fournisseur($user, $id_fourn, $ref_fourn, $quantity)
Add a supplier price for the product.
const STATUS_OPEN_INTERNAL
Warehouse open and operations for stock transfers/corrections allowed (not for customer shipping and ...
check_barcode($valuetotest, $typefortest)
Check barcode.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
Class to manage categories.
$tva_npr
French VAT NPR (0 or 1)
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Create a document onto disk according to template module.
dol_strlen($string, $stringencoding= 'UTF-8')
Make a strlen call.
price2num($amount, $rounding= '', $option=0)
Function that return a number with universal decimal format (decimal separator is '...
delete_photo($file)
Efface la photo du produit et sa vignette.
measuring_units_squared($unit)
Transform a given unit scale into the square of that unit, if known.
static commonReplaceThirdparty(DoliDB $db, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
img_picto($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt= '', $morecss= '', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
get_image_size($file)
Load size of image file.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
_log_price($user, $level=0)
Insert a track that we changed a customer price.
dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories) ...
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1)
Remove a file or several files with a mask.
img_object($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
min_recommended_price()
Return minimum product recommended price.
deleteExtraFields()
Delete all extra fields values for the current object.
dol_sanitizeFileName($str, $newstr= '_', $unaccent=1)
Clean a string to use it as a file name.
_get_stats($sql, $mode, $year=0)
Return an array formated for showing graphs.
utf8_check($str)
Check if a string is in UTF8.
Class ProductCombination Used to represent a product combination.
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disablevirusscan=0, $uploaderrorcode=0, $nohook=0, $varfiles= 'addedfile', $upload_dir= '')
Make control on an uploaded file from an GUI page and move it to final destination.
isService()
Return if object is a product.
dol_is_file($pathoffile)
Return if path is a file.
add_photo($sdir, $file)
Move an uploaded file described into $file array into target directory $sdir.
const STATUS_VALIDATED
Validated status.
fetch($id= '', $ref= '', $ref_ext= '', $barcode= '', $ignore_expression=0, $ignore_price_load=0, $ignore_lang_load=0)
Load a product in memory from database.
print $_SERVER["PHP_SELF"]
Edit parameters.
load_virtual_stock($includedraftpoforvirtual=null)
Load value ->stock_theorique of a product.
fetch_prod_arbo($prod, $compl_path="", $multiply=1, $level=1, $id_parent=0)
Fonction recursive uniquement utilisee par get_arbo_each_prod, recompose l'arborescence des sousprodu...
static findAll($db, $fk_product_stock, $with_qty=0, $fk_product=0)
Return all batch detail records for a given product and warehouse.
setAccountancyCode($type, $value)
Sets an accountancy code for a product.
load_stats_reception($socid=0, $filtrestatut= '', $forVirtualStock=0)
Charge tableau des stats réception fournisseur pour le produit/service.
delMultiLangs($langtodelete, $user)
Delete a language for this product.
Manage record for batch number management.
$pmp
Average price value for product entry into stock (PMP)
dol_print_date($time, $format= '', $tzoutput= 'auto', $outputlangs= '', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
call_trigger($triggerName, $user)
Call trigger based on this instance.
update($id, $user, $notrigger=false, $action= 'update', $updatetype=false)
Update a record into database.
measuring_units_cubed($unit)
Transform a given unit scale into the cube of that unit, if known.
getNomUrl($withpicto=0, $option= '', $maxlength=0, $save_lastsearch_value=-1, $notooltip=0)
Return clicable link of object (with eventually picto)
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->don->lire) if(!empty($conf->tax->enabled)&&$user->rights->tax->charges->lire) if(!empty($conf->facture->enabled)&&!empty($conf->commande->enabled)&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
dol_print_error($db= '', $error= '', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that return vat rate of a product line (according to seller, buyer and product vat rate) Si ...
get_sousproduits_arbo()
Return tree of all subproducts for product.
get_buyprice($prodfournprice, $qty, $product_id=0, $fourn_ref= '', $fk_soc=0)
Read price used by a provider.
dol_trunc($string, $size=40, $trunc= 'right', $stringencoding= 'UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '...' if string larger than length.
dolGetStatus($statusLabel= '', $statusLabelShort= '', $html= '', $statusType= 'status0', $displayMode=0, $url= '', $params=array())
Output the badge of a status.
load_state_board()
Load indicators this->nb for the dashboard.
log_price_delete($user, $rowid)
Delete a price line.
clone_associations($fromId, $toId)
Clone links between products.
show_photos($modulepart, $sdir, $size=0, $nbmax=0, $nbbyrow=5, $showfilename=0, $showaction=0, $maxHeight=120, $maxWidth=160, $nolink=0, $notitle=0, $usesharelink=0)
Show photos of an object (nbmax maximum), into several columns.
get_nb_order($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter= '')
Return nb of units in orders in which product is included.
setCategories($categories)
Sets object to supplied categories.
getMultiLangs()
Load array this->multilangs.
get_nb_mos($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter= '')
Return nb of units in orders in which product is included.
correct_stock_batch($user, $id_entrepot, $nbpiece, $movement, $label= '', $price=0, $dlc= '', $dluo= '', $lot= '', $inventorycode= '', $origin_element= '', $origin_id=null, $disablestockchangeforsubproduct=0)
Adjust stock in a warehouse for product with batch number.
hasFatherOrChild($mode=0)
Count all parent and children products for current product (first level only)
load_stats_contrat($socid=0)
Charge tableau des stats contrat pour le produit/service.
check()
Check that ref and label are ok.
length_accountg($account)
Return General accounting account with defined length (used for product and miscellaneous) ...
get_nb_ordersupplier($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter= '')
Return nb of units in orders in which product is included.
getLibStatut($mode=0, $type=0)
Return label of status of object.
get_nb_propalsupplier($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter= '')
Return nb of units in proposals in which product is included.
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
load_stats_proposal_supplier($socid=0)
Charge tableau des stats propale pour le produit/service.
getCountry($searchkey, $withcode= '', $dbtouse=0, $outputlangs= '', $entconv=1, $searchlabel= '')
Return country label, code or id from an id, code or label.
generateMultiprices(User $user, $baseprice, $price_type, $price_vat, $npr, $psq)
Generates prices for a product based on product multiprice generation rules.
get_nb_propal($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter= '')
Return nb of units in proposals in which product is included.
Parent class of all other business classes (invoices, contracts, proposals, orders, ...)
Class to manage predefined suppliers products.
if(!empty($search_group)) natural_search(array("g.nom"g note
load_stats_mo($socid=0)
Charge tableau des stats OF pour le produit/service.
dol_mkdir($dir, $dataroot= '', $newmask=null)
Creation of a directory (this can create recursive subdir)
getSellPrice($thirdparty_seller, $thirdparty_buyer, $pqp=0)
Return price of sell of a product for a seller/buyer/product.
measuringUnitString($unit, $measuring_style= '', $scale= '', $use_short_label=0, $outputlangs=null)
Return translation label of a unit key.
hasbatch()
Return if object has a sell-by date or eat-by date.
__construct($db)
Constructor.