40require_once DOL_DOCUMENT_ROOT.
'/core/lib/product.lib.php';
41require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobject.class.php';
42require_once DOL_DOCUMENT_ROOT.
'/product/class/productbatch.class.php';
43require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/productlot.class.php';
44require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/entrepot.class.php';
55 const SELL_OR_EAT_BY_MANDATORY_ID_SELL_BY = 1;
56 const SELL_OR_EAT_BY_MANDATORY_ID_EAT_BY = 2;
57 const SELL_OR_EAT_BY_MANDATORY_ID_SELL_AND_EAT = 3;
62 public $element =
'product';
67 public $table_element =
'product';
72 public $fk_element =
'fk_product';
82 protected $childtables = array(
83 'supplier_proposaldet' => array(
'name' =>
'SupplierProposal',
'parent' =>
'supplier_proposal',
'parentkey' =>
'fk_supplier_proposal'),
84 'propaldet' => array(
'name' =>
'Proposal',
'parent' =>
'propal',
'parentkey' =>
'fk_propal'),
85 'commandedet' => array(
'name' =>
'Order',
'parent' =>
'commande',
'parentkey' =>
'fk_commande'),
86 'facturedet' => array(
'name' =>
'Invoice',
'parent' =>
'facture',
'parentkey' =>
'fk_facture'),
87 'contratdet' => array(
'name' =>
'Contract',
'parent' =>
'contrat',
'parentkey' =>
'fk_contrat'),
88 'facture_fourn_det' => array(
'name' =>
'SupplierInvoice',
'parent' =>
'facture_fourn',
'parentkey' =>
'fk_facture_fourn'),
89 'commande_fournisseurdet' => array(
'name' =>
'SupplierOrder',
'parent' =>
'commande_fournisseur',
'parentkey' =>
'fk_commande'),
90 'mrp_production' => array(
'name' =>
'Mo',
'parent' =>
'mrp_mo',
'parentkey' =>
'fk_mo',
'enabled' =>
'isModEnabled("mrp")'),
91 'bom_bom' => array(
'name' =>
'BOM',
'enabled' =>
'isModEnabled("bom")'),
92 'bom_bomline' => array(
'name' =>
'BOMLine',
'parent' =>
'bom_bom',
'parentkey' =>
'fk_bom',
'enabled' =>
'isModEnabled("bom")'),
98 public $picto =
'product';
105 public $regeximgext =
'\.gif|\.jpg|\.jpeg|\.png|\.bmp|\.webp|\.xpm|\.xbm';
148 public $price_formated;
157 public $price_ttc_formated;
171 public $price_min_ttc;
177 public $price_base_type;
182 public $multiprices_ttc = array();
183 public $multiprices_base_type = array();
184 public $multiprices_default_vat_code = array();
185 public $multiprices_min = array();
186 public $multiprices_min_ttc = array();
187 public $multiprices_tva_tx = array();
188 public $multiprices_recuperableonly = array();
192 public $prices_by_qty = array();
193 public $prices_by_qty_id = array();
194 public $prices_by_qty_list = array();
220 public $localtax2_tx;
221 public $localtax1_type;
222 public $localtax2_type;
226 public $desc_supplier;
227 public $vatrate_supplier;
228 public $default_vat_code_supplier;
229 public $fourn_multicurrency_price;
230 public $fourn_multicurrency_unitprice;
231 public $fourn_multicurrency_tx;
232 public $fourn_multicurrency_id;
233 public $fourn_multicurrency_code;
239 public $qc_frequency;
246 public $stock_reel = 0;
253 public $stock_theorique;
270 public $seuil_stock_alerte = 0;
293 public $fk_default_workstation;
315 public $status_buy = 0;
337 public $fk_default_bom;
344 public $product_fourn_price_id;
366 public $status_batch = 0;
373 public $sell_or_eat_by_mandatory = 0;
380 public $batch_mask =
'';
398 public $weight_units;
400 public $length_units;
404 public $height_units;
406 public $surface_units;
408 public $volume_units;
411 public $net_measure_units;
413 public $accountancy_code_sell;
414 public $accountancy_code_sell_intra;
415 public $accountancy_code_sell_export;
416 public $accountancy_code_buy;
417 public $accountancy_code_buy_intra;
418 public $accountancy_code_buy_export;
428 public $barcode_type;
433 public $barcode_type_code;
435 public $stats_propale = array();
436 public $stats_commande = array();
437 public $stats_contrat = array();
438 public $stats_facture = array();
439 public $stats_proposal_supplier = array();
440 public $stats_commande_fournisseur = array();
441 public $stats_expedition = array();
442 public $stats_reception = array();
443 public $stats_mo = array();
444 public $stats_bom = array();
445 public $stats_mrptoconsume = array();
446 public $stats_mrptoproduce = array();
447 public $stats_facturerec = array();
448 public $stats_facture_fournisseur = array();
457 public $date_creation;
462 public $date_modification;
478 public $fk_default_warehouse;
482 public $fk_price_expression;
487 public $fourn_price_base_type;
503 public $ref_supplier;
517 public $price_autogen = 0;
524 public $supplierprices;
544 public $is_object_used;
546 public $is_sousproduit_qty;
547 public $is_sousproduit_incdec;
549 public $mandatory_period;
580 public $fields = array(
581 'rowid' => array(
'type' =>
'integer',
'label' =>
'TechnicalID',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'index' => 1,
'position' => 1,
'comment' =>
'Id'),
582 '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'),
583 'entity' => array(
'type' =>
'integer',
'label' =>
'Entity',
'enabled' => 1,
'visible' => 0,
'default' =>
'1',
'notnull' => 1,
'index' => 1,
'position' => 5),
584 'label' => array(
'type' =>
'varchar(255)',
'label' =>
'Label',
'enabled' => 1,
'visible' => 1,
'notnull' => 1,
'showoncombobox' => 2,
'position' => 15,
'csslist' =>
'tdoverflowmax250'),
585 'barcode' => array(
'type' =>
'varchar(255)',
'label' =>
'Barcode',
'enabled' =>
'isModEnabled("barcode")',
'position' => 20,
'visible' => -1,
'showoncombobox' => 3,
'cssview' =>
'tdwordbreak',
'csslist' =>
'tdoverflowmax125'),
586 'fk_barcode_type' => array(
'type' =>
'integer',
'label' =>
'BarcodeType',
'enabled' => 1,
'position' => 21,
'notnull' => 0,
'visible' => -1,),
587 'note_public' => array(
'type' =>
'html',
'label' =>
'NotePublic',
'enabled' => 1,
'visible' => 0,
'position' => 61),
588 'note' => array(
'type' =>
'html',
'label' =>
'NotePrivate',
'enabled' => 1,
'visible' => 0,
'position' => 62),
589 'datec' => array(
'type' =>
'datetime',
'label' =>
'DateCreation',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 500),
590 'tms' => array(
'type' =>
'timestamp',
'label' =>
'DateModification',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 501),
592 'fk_user_author' => array(
'type' =>
'integer',
'label' =>
'UserAuthor',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 510,
'foreignkey' =>
'llx_user.rowid'),
593 'fk_user_modif' => array(
'type' =>
'integer',
'label' =>
'UserModif',
'enabled' => 1,
'visible' => -2,
'notnull' => -1,
'position' => 511),
595 'localtax1_tx' => array(
'type' =>
'double(6,3)',
'label' =>
'Localtax1tx',
'enabled' => 1,
'position' => 150,
'notnull' => 0,
'visible' => -1,),
596 'localtax1_type' => array(
'type' =>
'varchar(10)',
'label' =>
'Localtax1type',
'enabled' => 1,
'position' => 155,
'notnull' => 1,
'visible' => -1,),
597 'localtax2_tx' => array(
'type' =>
'double(6,3)',
'label' =>
'Localtax2tx',
'enabled' => 1,
'position' => 160,
'notnull' => 0,
'visible' => -1,),
598 'localtax2_type' => array(
'type' =>
'varchar(10)',
'label' =>
'Localtax2type',
'enabled' => 1,
'position' => 165,
'notnull' => 1,
'visible' => -1,),
599 'last_main_doc' => array(
'type' =>
'varchar(255)',
'label' =>
'LastMainDoc',
'enabled' => 1,
'visible' => -1,
'position' => 170),
600 'import_key' => array(
'type' =>
'varchar(14)',
'label' =>
'ImportId',
'enabled' => 1,
'visible' => -2,
'notnull' => -1,
'index' => 0,
'position' => 1000),
603 'mandatory_period' => array(
'type' =>
'integer',
'label' =>
'mandatoryperiod',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'default' =>
'0',
'index' => 1,
'position' => 1000),
624 $this->ismultientitymanaged = 1;
625 $this->isextrafieldmanaged = 1;
638 $this->
ref = trim($this->
ref);
666 public function create($user, $notrigger = 0)
668 global $conf, $langs;
674 $this->
ref = trim($this->
ref);
678 $this->label = trim($this->label);
679 $this->price_ttc = (float)
price2num($this->price_ttc);
681 $this->price_min_ttc = (float)
price2num($this->price_min_ttc);
682 $this->price_min = (float)
price2num($this->price_min);
683 $this->price_label = trim($this->price_label);
684 if (empty($this->tva_tx)) {
687 if (empty($this->tva_npr)) {
691 if (empty($this->localtax1_tx)) {
692 $this->localtax1_tx = 0;
694 if (empty($this->localtax2_tx)) {
695 $this->localtax2_tx = 0;
697 if (empty($this->localtax1_type)) {
698 $this->localtax1_type =
'0';
700 if (empty($this->localtax2_type)) {
701 $this->localtax2_type =
'0';
703 if (empty($this->
price)) {
706 if (empty($this->price_min)) {
707 $this->price_min = 0;
710 if (empty($this->price_by_qty)) {
711 $this->price_by_qty = 0;
714 if (empty($this->
status)) {
717 if (empty($this->status_buy)) {
718 $this->status_buy = 0;
727 if ($this->price_base_type ==
'TTC' && $this->price_ttc > 0) {
728 $price_ttc =
price2num($this->price_ttc,
'MU');
729 $price_ht =
price2num($this->price_ttc / (1 + ($this->tva_tx / 100)),
'MU');
733 if ($this->price_base_type !=
'TTC' && $this->
price > 0) {
735 $price_ttc =
price2num($this->
price * (1 + ($this->tva_tx / 100)),
'MU');
739 if (($this->price_min_ttc > 0) && ($this->price_base_type ==
'TTC')) {
740 $price_min_ttc =
price2num($this->price_min_ttc,
'MU');
741 $price_min_ht =
price2num($this->price_min_ttc / (1 + ($this->tva_tx / 100)),
'MU');
745 if (($this->price_min > 0) && ($this->price_base_type !=
'TTC')) {
746 $price_min_ht =
price2num($this->price_min,
'MU');
747 $price_min_ttc =
price2num($this->price_min * (1 + ($this->tva_tx / 100)),
'MU');
750 $this->accountancy_code_buy = trim($this->accountancy_code_buy);
751 $this->accountancy_code_buy_intra = trim($this->accountancy_code_buy_intra);
752 $this->accountancy_code_buy_export = trim($this->accountancy_code_buy_export);
753 $this->accountancy_code_sell = trim($this->accountancy_code_sell);
754 $this->accountancy_code_sell_intra = trim($this->accountancy_code_sell_intra);
755 $this->accountancy_code_sell_export = trim($this->accountancy_code_sell_export);
758 $this->barcode = trim($this->barcode);
759 $this->mandatory_period = empty($this->mandatory_period) ? 0 : $this->mandatory_period;
761 if (empty($this->label)) {
762 $this->error =
'ErrorMandatoryParametersNotProvided';
766 if (empty($this->
ref) || $this->
ref ==
'auto') {
769 if ($module !=
'mod_codeproduct_leopard') {
770 if (substr($module, 0, 16) ==
'mod_codeproduct_' && substr($module, -3) ==
'php') {
771 $module = substr($module, 0,
dol_strlen($module) - 4);
774 $modCodeProduct =
new $module();
775 '@phan-var-force ModeleProductCode $modCodeProduct';
776 if (!empty($modCodeProduct->code_auto)) {
777 $this->
ref = $modCodeProduct->getNextValue($this, $this->
type);
779 unset($modCodeProduct);
782 if (empty($this->
ref)) {
783 $this->error =
'ProductModuleNotSetupForAutoRef';
788 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);
792 if (empty($this->date_creation)) {
793 $this->date_creation = $now;
799 if ($this->barcode ==
'-1' || $this->barcode ==
'auto') {
800 $this->barcode = $this->
get_barcode($this, $this->barcode_type_code);
805 $result = $this->
verify();
808 $sql =
"SELECT count(*) as nb";
809 $sql .=
" FROM ".$this->db->prefix().
"product";
810 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
811 $sql .=
" AND ref = '".$this->db->escape($this->
ref).
"'";
813 $result = $this->db->query($sql);
815 $obj = $this->db->fetch_object($result);
818 $sql =
"INSERT INTO ".$this->db->prefix().
"product (";
823 $sql .=
", price_min";
824 $sql .=
", price_min_ttc";
826 $sql .=
", fk_user_author";
827 $sql .=
", fk_product_type";
829 $sql .=
", price_ttc";
830 $sql .=
", price_base_type";
831 $sql .=
", price_label";
835 $sql .=
", accountancy_code_buy";
836 $sql .=
", accountancy_code_buy_intra";
837 $sql .=
", accountancy_code_buy_export";
838 $sql .=
", accountancy_code_sell";
839 $sql .=
", accountancy_code_sell_intra";
840 $sql .=
", accountancy_code_sell_export";
843 $sql .=
", finished";
845 $sql .=
", sell_or_eat_by_mandatory";
846 $sql .=
", batch_mask";
848 $sql .=
", mandatory_period";
849 $sql .=
") VALUES (";
850 $sql .=
"'".$this->db->idate($this->date_creation).
"'";
851 $sql .=
", ".(!empty($this->entity) ? (int) $this->entity : (int) $conf->entity);
852 $sql .=
", '".$this->db->escape($this->
ref).
"'";
853 $sql .=
", ".(!empty($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
854 $sql .=
", ".price2num($price_min_ht);
855 $sql .=
", ".price2num($price_min_ttc);
856 $sql .=
", ".(!empty($this->label) ?
"'".$this->db->escape($this->label).
"'" :
"null");
857 $sql .=
", ".((int) $user->id);
858 $sql .=
", ".((int) $this->
type);
859 $sql .=
", ".price2num($price_ht,
'MT');
860 $sql .=
", ".price2num($price_ttc,
'MT');
861 $sql .=
", '".$this->db->escape($this->price_base_type).
"'";
862 $sql .=
", ".(!empty($this->price_label) ?
"'".$this->db->escape($this->price_label).
"'" :
"null");
863 $sql .=
", ".((int) $this->
status);
864 $sql .=
", ".((int) $this->status_buy);
866 $sql .=
", '".$this->db->escape($this->accountancy_code_buy).
"'";
867 $sql .=
", '".$this->db->escape($this->accountancy_code_buy_intra).
"'";
868 $sql .=
", '".$this->db->escape($this->accountancy_code_buy_export).
"'";
869 $sql .=
", '".$this->db->escape($this->accountancy_code_sell).
"'";
870 $sql .=
", '".$this->db->escape($this->accountancy_code_sell_intra).
"'";
871 $sql .=
", '".$this->db->escape($this->accountancy_code_sell_export).
"'";
873 $sql .=
", '".$this->db->escape($this->canvas).
"'";
874 $sql .=
", ".((!isset($this->finished) || $this->finished < 0 || $this->finished ==
'') ?
'NULL' : (int) $this->finished);
875 $sql .=
", ".((empty($this->status_batch) || $this->status_batch < 0) ?
'0' : ((int) $this->status_batch));
876 $sql .=
", ".((empty($this->sell_or_eat_by_mandatory) || $this->sell_or_eat_by_mandatory < 0) ? 0 : ((int) $this->sell_or_eat_by_mandatory));
877 $sql .=
", '".$this->db->escape($this->batch_mask).
"'";
878 $sql .=
", ".($this->fk_unit > 0 ? ((int) $this->fk_unit) :
'NULL');
879 $sql .=
", '".$this->db->escape($this->mandatory_period).
"'";
882 dol_syslog(get_class($this).
"::Create", LOG_DEBUG);
884 $result = $this->db->query($sql);
886 $id = $this->db->last_insert_id($this->db->prefix().
"product");
890 $this->
price = $price_ht;
891 $this->price_ttc = $price_ttc;
892 $this->price_min = $price_min_ht;
893 $this->price_min_ttc = $price_min_ttc;
897 if ($this->
update($id, $user,
true,
'add') <= 0) {
902 $this->error = $this->db->lasterror();
907 $this->db->query(
"DELETE FROM " . $this->db->prefix() .
"product_perentity WHERE fk_product = " .((int) $this->id) .
" AND entity = " . ((
int) $conf->entity));
909 $sql =
"INSERT INTO " . $this->db->prefix() .
"product_perentity (";
910 $sql .=
" fk_product";
912 $sql .=
", accountancy_code_buy";
913 $sql .=
", accountancy_code_buy_intra";
914 $sql .=
", accountancy_code_buy_export";
915 $sql .=
", accountancy_code_sell";
916 $sql .=
", accountancy_code_sell_intra";
917 $sql .=
", accountancy_code_sell_export";
918 $sql .=
") VALUES (";
920 $sql .=
", " . $conf->entity;
921 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy) .
"'";
922 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_intra) .
"'";
923 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_export) .
"'";
924 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell) .
"'";
925 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_intra) .
"'";
926 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_export) .
"'";
928 $result = $this->db->query($sql);
931 $this->error =
'ErrorFailedToInsertAccountancyForEntity';
936 $this->error =
'ErrorFailedToGetInsertedId';
940 $this->error = $this->db->lasterror();
944 $langs->load(
"products");
946 $this->error =
"ErrorProductAlreadyExists";
947 dol_syslog(get_class($this).
"::Create fails, ref ".$this->
ref.
" already exists");
951 $this->error = $this->db->lasterror();
954 if (!$error && !$notrigger) {
967 $this->db->rollback();
971 $this->db->rollback();
972 dol_syslog(get_class($this).
"::Create fails verify ".implode(
',', $this->errors), LOG_WARNING);
988 $this->errors = array();
991 $this->
ref = trim($this->
ref);
994 $this->errors[] =
'ErrorBadRef';
998 $arrayofnonnegativevalue = array(
'weight' =>
'Weight',
'width' =>
'Width',
'height' =>
'Height',
'length' =>
'Length',
'surface' =>
'Surface',
'volume' =>
'Volume');
999 foreach ($arrayofnonnegativevalue as $key => $value) {
1000 if (property_exists($this, $key) && !empty($this->$key) && ($this->$key < 0)) {
1001 $langs->loadLangs(array(
"main",
"other"));
1002 $this->error = $langs->trans(
"FieldCannotBeNegative", $langs->transnoentitiesnoconv($value));
1003 $this->errors[] = $this->error;
1008 $rescode = $this->
check_barcode($this->barcode, $this->barcode_type_code);
1010 if ($rescode == -1) {
1011 $this->errors[] =
'ErrorBadBarCodeSyntax';
1012 } elseif ($rescode == -2) {
1013 $this->errors[] =
'ErrorBarCodeRequired';
1014 } elseif ($rescode == -3) {
1016 $this->errors[] =
'ErrorBarCodeAlreadyUsed';
1043 $dirsociete = array_merge(array(
'/core/modules/barcode/'), $conf->modules_parts[
'barcode']);
1044 foreach ($dirsociete as $dirroot) {
1051 $mod =
new $module();
1052 '@phan-var-force ModeleNumRefBarCode $mod';
1054 dol_syslog(get_class($this).
"::check_barcode value=".$valuetotest.
" type=".$typefortest.
" module=".$module);
1055 $result = $mod->verif($this->db, $valuetotest, $this, 0, $typefortest);
1073 public function update($id, $user, $notrigger = 0, $action =
'update', $updatetype =
false)
1075 global $langs, $conf, $hookmanager;
1080 if (!$this->label) {
1081 $this->label =
'MISSING LABEL';
1086 $this->
ref = trim($this->
ref);
1090 $this->label = trim($this->label);
1092 $this->note_private = (isset($this->note_private) ? trim($this->note_private) :
null);
1093 $this->note_public = (isset($this->note_public) ? trim($this->note_public) :
null);
1094 $this->net_measure =
price2num($this->net_measure);
1095 $this->net_measure_units = (empty($this->net_measure_units) ?
'' : trim($this->net_measure_units));
1096 $this->weight =
price2num($this->weight);
1097 $this->weight_units = (empty($this->weight_units) ?
'' : trim($this->weight_units));
1098 $this->length =
price2num($this->length);
1099 $this->length_units = (empty($this->length_units) ?
'' : trim($this->length_units));
1101 $this->width_units = (empty($this->width_units) ?
'' : trim($this->width_units));
1102 $this->height =
price2num($this->height);
1103 $this->height_units = (empty($this->height_units) ?
'' : trim($this->height_units));
1104 $this->surface =
price2num($this->surface);
1105 $this->surface_units = (empty($this->surface_units) ?
'' : trim($this->surface_units));
1106 $this->volume =
price2num($this->volume);
1107 $this->volume_units = (empty($this->volume_units) ?
'' : trim($this->volume_units));
1110 if (is_numeric($this->length_units)) {
1111 $this->width_units = $this->length_units;
1113 if (is_numeric($this->length_units)) {
1114 $this->height_units = $this->length_units;
1118 if (empty($this->surface) && !empty($this->length) && !empty($this->width) && $this->length_units == $this->width_units) {
1119 $this->surface = (float) $this->length * (
float) $this->width;
1122 if (empty($this->volume) && !empty($this->surface) && !empty($this->height) && $this->length_units == $this->height_units) {
1123 $this->volume = $this->surface * (float) $this->height;
1127 if (empty($this->tva_tx)) {
1130 if (empty($this->tva_npr)) {
1133 if (empty($this->localtax1_tx)) {
1134 $this->localtax1_tx = 0;
1136 if (empty($this->localtax2_tx)) {
1137 $this->localtax2_tx = 0;
1139 if (empty($this->localtax1_type)) {
1140 $this->localtax1_type =
'0';
1142 if (empty($this->localtax2_type)) {
1143 $this->localtax2_type =
'0';
1145 if (empty($this->
status)) {
1148 if (empty($this->status_buy)) {
1149 $this->status_buy = 0;
1152 if (empty($this->country_id)) {
1153 $this->country_id = 0;
1156 if (empty($this->state_id)) {
1157 $this->state_id = 0;
1161 $this->barcode = (empty($this->barcode) ?
'' : trim($this->barcode));
1163 $this->accountancy_code_buy = trim($this->accountancy_code_buy);
1164 $this->accountancy_code_buy_intra = (!empty($this->accountancy_code_buy_intra) ? trim($this->accountancy_code_buy_intra) :
'');
1165 $this->accountancy_code_buy_export = trim($this->accountancy_code_buy_export);
1166 $this->accountancy_code_sell = trim($this->accountancy_code_sell);
1167 $this->accountancy_code_sell_intra = trim($this->accountancy_code_sell_intra);
1168 $this->accountancy_code_sell_export = trim($this->accountancy_code_sell_export);
1175 if ($action !=
'add') {
1176 $result = $this->
verify();
1184 if (is_null($this->oldcopy) || (is_object($this->oldcopy) && $this->oldcopy->isEmpty())) {
1189 if ($this->
hasbatch() && !$this->oldcopy->hasbatch()) {
1191 $valueforundefinedlot =
'000000';
1196 dol_syslog(
"Flag batch of product id=".$this->
id.
" is set to ON, so we will create missing records into product_batch");
1199 foreach ($this->stock_warehouse as $idW => $ObjW) {
1201 foreach ($ObjW->detail_batch as $detail) {
1202 if ($detail->batch == $valueforundefinedlot || $detail->batch ==
'Undefined') {
1204 $sqlclean =
"DELETE FROM ".$this->db->prefix().
"product_batch WHERE batch in('Undefined', '".$this->db->escape($valueforundefinedlot).
"') AND fk_product_stock = ".((int) $ObjW->id);
1205 $result = $this->db->query($sqlclean);
1213 $qty_batch += $detail->qty;
1217 if ($ObjW->real != $qty_batch) {
1219 $ObjBatch->batch = $valueforundefinedlot;
1220 $ObjBatch->qty = ($ObjW->real - $qty_batch);
1221 $ObjBatch->fk_product_stock = $ObjW->id;
1223 if ($ObjBatch->create($user, 1) < 0) {
1225 $this->errors = $ObjBatch->errors;
1230 if ($ObjLot->fetch(0, $this->id, $valueforundefinedlot) == 0) {
1231 $ObjLot->fk_product = $this->id;
1232 $ObjLot->entity = $this->entity;
1233 $ObjLot->fk_user_creat = $user->id;
1234 $ObjLot->batch = $valueforundefinedlot;
1235 if ($ObjLot->create($user,
true) < 0) {
1237 $this->errors = $ObjLot->errors;
1246 if ($this->barcode == -1) {
1247 $this->barcode = $this->
get_barcode($this, $this->barcode_type_code);
1250 $sql =
"UPDATE ".$this->db->prefix().
"product";
1251 $sql .=
" SET label = '".$this->db->escape($this->label).
"'";
1254 $sql .=
", fk_product_type = ".((int) $this->
type);
1257 $sql .=
", ref = '".$this->db->escape($this->
ref).
"'";
1258 $sql .=
", ref_ext = ".(!empty($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
1259 $sql .=
", default_vat_code = ".($this->default_vat_code ?
"'".$this->db->escape($this->default_vat_code).
"'" :
"null");
1260 $sql .=
", tva_tx = ".((float) $this->tva_tx);
1261 $sql .=
", recuperableonly = ".((int) $this->tva_npr);
1262 $sql .=
", localtax1_tx = ".((float) $this->localtax1_tx);
1263 $sql .=
", localtax2_tx = ".((float) $this->localtax2_tx);
1264 $sql .=
", localtax1_type = ".($this->localtax1_type !=
'' ?
"'".$this->db->escape($this->localtax1_type).
"'" :
"'0'");
1265 $sql .=
", localtax2_type = ".($this->localtax2_type !=
'' ?
"'".$this->db->escape($this->localtax2_type).
"'" :
"'0'");
1267 $sql .=
", barcode = ".(empty($this->barcode) ?
"null" :
"'".$this->db->escape($this->barcode).
"'");
1268 $sql .=
", fk_barcode_type = ".(empty($this->barcode_type) ?
"null" : $this->db->escape($this->barcode_type));
1270 $sql .=
", tosell = ".(int) $this->
status;
1271 $sql .=
", tobuy = ".(int) $this->status_buy;
1272 $sql .=
", tobatch = ".((empty($this->status_batch) || $this->status_batch < 0) ?
'0' : (int) $this->status_batch);
1273 $sql .=
", sell_or_eat_by_mandatory = ".((empty($this->sell_or_eat_by_mandatory) || $this->sell_or_eat_by_mandatory < 0) ? 0 : (int) $this->sell_or_eat_by_mandatory);
1274 $sql .=
", batch_mask = '".$this->db->escape($this->batch_mask).
"'";
1276 $sql .=
", finished = ".((!isset($this->finished) || $this->finished < 0 || $this->finished ===
'') ?
"null" : (int) $this->finished);
1277 $sql .=
", fk_default_bom = ".((!isset($this->fk_default_bom) || $this->fk_default_bom < 0 || $this->fk_default_bom ==
'') ?
"null" : (int) $this->fk_default_bom);
1278 $sql .=
", net_measure = ".($this->net_measure !=
'' ?
"'".$this->db->escape($this->net_measure).
"'" :
'null');
1279 $sql .=
", net_measure_units = ".($this->net_measure_units !=
'' ?
"'".$this->db->escape($this->net_measure_units).
"'" :
'null');
1280 $sql .=
", weight = ".($this->weight !=
'' ?
"'".$this->db->escape($this->weight).
"'" :
'null');
1281 $sql .=
", weight_units = ".($this->weight_units !=
'' ?
"'".$this->db->escape($this->weight_units).
"'" :
'null');
1282 $sql .=
", length = ".($this->length !=
'' ?
"'".$this->db->escape($this->length).
"'" :
'null');
1283 $sql .=
", length_units = ".($this->length_units !=
'' ?
"'".$this->db->escape($this->length_units).
"'" :
'null');
1284 $sql .=
", width= ".($this->width !=
'' ?
"'".$this->db->escape($this->width).
"'" :
'null');
1285 $sql .=
", width_units = ".($this->width_units !=
'' ?
"'".$this->db->escape($this->width_units).
"'" :
'null');
1286 $sql .=
", height = ".($this->height !=
'' ?
"'".$this->db->escape($this->height).
"'" :
'null');
1287 $sql .=
", height_units = ".($this->height_units !=
'' ?
"'".$this->db->escape($this->height_units).
"'" :
'null');
1288 $sql .=
", surface = ".($this->surface !=
'' ?
"'".$this->db->escape($this->surface).
"'" :
'null');
1289 $sql .=
", surface_units = ".($this->surface_units !=
'' ?
"'".$this->db->escape($this->surface_units).
"'" :
'null');
1290 $sql .=
", volume = ".($this->volume !=
'' ?
"'".$this->db->escape($this->volume).
"'" :
'null');
1291 $sql .=
", volume_units = ".($this->volume_units !=
'' ?
"'".$this->db->escape($this->volume_units).
"'" :
'null');
1292 $sql .=
", fk_default_warehouse = ".($this->fk_default_warehouse > 0 ? ((int) $this->fk_default_warehouse) :
'null');
1293 $sql .=
", fk_default_workstation = ".($this->fk_default_workstation > 0 ? ((int) $this->fk_default_workstation) :
'null');
1294 $sql .=
", seuil_stock_alerte = ".((isset($this->seuil_stock_alerte) && is_numeric($this->seuil_stock_alerte)) ? (
float) $this->seuil_stock_alerte :
'null');
1295 $sql .=
", description = '".$this->db->escape($this->
description).
"'";
1296 $sql .=
", url = ".($this->url ?
"'".$this->db->escape($this->url).
"'" :
'null');
1297 $sql .=
", customcode = '".$this->db->escape($this->customcode).
"'";
1298 $sql .=
", fk_country = ".($this->country_id > 0 ? (int) $this->country_id :
'null');
1299 $sql .=
", fk_state = ".($this->state_id > 0 ? (int) $this->state_id :
'null');
1300 $sql .=
", lifetime = ".($this->lifetime > 0 ? (int) $this->lifetime :
'null');
1301 $sql .=
", qc_frequency = ".($this->qc_frequency > 0 ? (int) $this->qc_frequency :
'null');
1302 $sql .=
", note = ".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
'null');
1303 $sql .=
", note_public = ".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
'null');
1304 $sql .=
", duration = '".$this->db->escape($this->duration_value.$this->duration_unit).
"'";
1306 $sql .=
", accountancy_code_buy = '" . $this->db->escape($this->accountancy_code_buy) .
"'";
1307 $sql .=
", accountancy_code_buy_intra = '" . $this->db->escape($this->accountancy_code_buy_intra) .
"'";
1308 $sql .=
", accountancy_code_buy_export = '" . $this->db->escape($this->accountancy_code_buy_export) .
"'";
1309 $sql .=
", accountancy_code_sell= '" . $this->db->escape($this->accountancy_code_sell) .
"'";
1310 $sql .=
", accountancy_code_sell_intra= '" . $this->db->escape($this->accountancy_code_sell_intra) .
"'";
1311 $sql .=
", accountancy_code_sell_export= '" . $this->db->escape($this->accountancy_code_sell_export) .
"'";
1313 $sql .=
", desiredstock = ".((isset($this->desiredstock) && is_numeric($this->desiredstock)) ? (
float) $this->desiredstock :
"null");
1314 $sql .=
", cost_price = ".($this->cost_price !=
'' ? $this->db->escape($this->cost_price) :
'null');
1315 $sql .=
", fk_unit= ".(!$this->fk_unit ?
'NULL' : (int) $this->fk_unit);
1316 $sql .=
", price_autogen = ".(!$this->price_autogen ? 0 : 1);
1317 $sql .=
", fk_price_expression = ".($this->fk_price_expression != 0 ? (int) $this->fk_price_expression :
'NULL');
1318 $sql .=
", fk_user_modif = ".($user->id > 0 ? $user->id :
'NULL');
1319 $sql .=
", mandatory_period = ".($this->mandatory_period);
1321 $sql .=
" WHERE rowid = ".((int) $id);
1323 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
1325 $resql = $this->db->query($sql);
1332 $this->db->rollback();
1341 $this->db->query(
"DELETE FROM " . $this->db->prefix() .
"product_perentity WHERE fk_product = " . ((
int) $this->id) .
" AND entity = " . ((
int) $conf->entity));
1343 $sql =
"INSERT INTO " . $this->db->prefix() .
"product_perentity (";
1344 $sql .=
" fk_product";
1346 $sql .=
", accountancy_code_buy";
1347 $sql .=
", accountancy_code_buy_intra";
1348 $sql .=
", accountancy_code_buy_export";
1349 $sql .=
", accountancy_code_sell";
1350 $sql .=
", accountancy_code_sell_intra";
1351 $sql .=
", accountancy_code_sell_export";
1352 $sql .=
") VALUES (";
1354 $sql .=
", " . $conf->entity;
1355 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy) .
"'";
1356 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_intra) .
"'";
1357 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_export) .
"'";
1358 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell) .
"'";
1359 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_intra) .
"'";
1360 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_export) .
"'";
1362 $result = $this->db->query($sql);
1365 $this->error =
'ErrorFailedToUpdateAccountancyForEntity';
1369 if (!$this->
hasbatch() && $this->oldcopy->hasbatch()) {
1371 $sql =
'SELECT pb.qty, ps.fk_entrepot, pb.batch FROM '.MAIN_DB_PREFIX.
'product_batch as pb';
1372 $sql .=
' INNER JOIN '.MAIN_DB_PREFIX.
'product_stock as ps ON (ps.rowid = pb.fk_product_stock)';
1373 $sql .=
' WHERE ps.fk_product = '.(int) $this->
id;
1375 $resql = $this->db->query($sql);
1379 while ($obj = $this->db->fetch_object($resql)) {
1381 $fk_entrepot = $obj->fk_entrepot;
1385 $batch = $obj->batch;
1388 $addOremove = $value > 0 ? 1 : 0;
1389 $label = $langs->trans(
'BatchStockMouvementAddInGlobal');
1390 $res = $this->
correct_stock_batch($user, $fk_entrepot, abs($value), $addOremove, $label, $price, $dlc, $dluo, $batch, $inventorycode,
'',
null, 0,
null,
true);
1393 $label = $langs->trans(
'BatchStockMouvementAddInGlobal');
1394 $res = $this->
correct_stock($user, $fk_entrepot, abs($value), (
int) empty($addOremove), $label, $price, $inventorycode,
'',
null, 0);
1413 if (!$error && !$notrigger) {
1415 $result = $this->
call_trigger(
'PRODUCT_MODIFY', $user);
1422 if (!$error && (is_object($this->oldcopy) && $this->oldcopy->ref !== $this->ref)) {
1424 if ($conf->product->dir_output) {
1427 if (file_exists($olddir)) {
1431 $res = @rename($olddir, $newdir);
1433 $langs->load(
"errors");
1434 $this->error = $langs->trans(
'ErrorFailToRenameDir', $olddir, $newdir);
1442 if (isModEnabled(
'variants')) {
1443 include_once DOL_DOCUMENT_ROOT.
'/variants/class/ProductCombination.class.php';
1447 foreach ($comb->fetchAllByFkProductParent($this->id) as $currcomb) {
1448 $currcomb->updateProperties($this, $user);
1452 $this->db->commit();
1455 $this->db->rollback();
1459 if ($this->db->errno() ==
'DB_ERROR_RECORD_ALREADY_EXISTS') {
1460 $langs->load(
"errors");
1461 if (empty($conf->barcode->enabled) || empty($this->barcode)) {
1462 $this->error = $langs->trans(
"Error").
" : ".$langs->trans(
"ErrorProductAlreadyExists", $this->
ref);
1464 $this->error = $langs->trans(
"Error").
" : ".$langs->trans(
"ErrorProductBarCodeAlreadyExists", $this->barcode);
1466 $this->errors[] = $this->error;
1467 $this->db->rollback();
1470 $this->error = $langs->trans(
"Error").
" : ".$this->db->error().
" - ".$sql;
1471 $this->errors[] = $this->error;
1472 $this->db->rollback();
1477 $this->db->rollback();
1478 dol_syslog(get_class($this).
"::Update fails verify ".implode(
',', $this->errors), LOG_WARNING);
1490 public function delete(
User $user, $notrigger = 0)
1492 global $conf, $langs;
1493 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1498 if (empty($this->
id)) {
1499 $this->error =
"Object must be fetched before calling delete";
1503 $this->error =
"ErrorForbidden";
1508 if (empty($objectisused)) {
1511 if (!$error && empty($notrigger)) {
1513 $result = $this->
call_trigger(
'PRODUCT_DELETE', $user);
1522 $sql =
"DELETE FROM ".$this->db->prefix().
'product_batch';
1523 $sql .=
" WHERE fk_product_stock IN (";
1524 $sql .=
"SELECT rowid FROM ".$this->db->prefix().
'product_stock';
1525 $sql .=
" WHERE fk_product = ".((int) $this->
id).
")";
1527 $result = $this->db->query($sql);
1530 $this->errors[] = $this->db->lasterror();
1536 $elements = array(
'product_fournisseur_price',
'product_price',
'product_lang',
'categorie_product',
'product_stock',
'product_customer_price',
'product_lot');
1537 foreach ($elements as $table) {
1539 $sql =
"DELETE FROM ".$this->db->prefix().$table;
1540 $sql .=
" WHERE fk_product = ".(int) $this->
id;
1542 $result = $this->db->query($sql);
1545 $this->errors[] = $this->db->lasterror();
1552 include_once DOL_DOCUMENT_ROOT.
'/variants/class/ProductCombination.class.php';
1553 include_once DOL_DOCUMENT_ROOT.
'/variants/class/ProductCombination2ValuePair.class.php';
1558 if ($prodcomb->deleteByFkProductParent($user, $this->id) < 0) {
1560 $this->errors[] =
'Error deleting combinations';
1564 if (!$error && ($prodcomb->fetchByFkProductChild($this->id) > 0) && ($prodcomb->delete($user) < 0)) {
1566 $this->errors[] =
'Error deleting child combination';
1572 $sql =
"DELETE FROM ".$this->db->prefix().
"product_association";
1573 $sql .=
" WHERE fk_product_pere = ".(int) $this->
id.
" OR fk_product_fils = ".(
int) $this->id;
1575 $result = $this->db->query($sql);
1578 $this->errors[] = $this->db->lasterror();
1587 dol_syslog(get_class($this).
"::delete error -4 ".$this->error, LOG_ERR);
1593 $sqlz =
"DELETE FROM ".$this->db->prefix().
"product";
1594 $sqlz .=
" WHERE rowid = ".(int) $this->
id;
1596 $resultz = $this->db->query($sqlz);
1599 $this->errors[] = $this->db->lasterror();
1615 if ($conf->product->dir_output) {
1616 $dir = $conf->product->dir_output.
"/".$ref;
1617 if (file_exists($dir)) {
1620 $this->errors[] =
'ErrorFailToDeleteDir';
1628 $this->db->commit();
1631 foreach ($this->errors as $errmsg) {
1632 dol_syslog(get_class($this).
"::delete ".$errmsg, LOG_ERR);
1633 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1635 $this->db->rollback();
1639 $this->error =
"ErrorRecordIsUsedCantDelete";
1653 $sellByLabel = $langs->trans(
'SellByDate');
1654 $eatByLabel = $langs->trans(
'EatByDate');
1656 self::SELL_OR_EAT_BY_MANDATORY_ID_NONE => $langs->trans(
'BatchSellOrEatByMandatoryNone'),
1657 self::SELL_OR_EAT_BY_MANDATORY_ID_SELL_BY => $sellByLabel,
1658 self::SELL_OR_EAT_BY_MANDATORY_ID_EAT_BY => $eatByLabel,
1659 self::SELL_OR_EAT_BY_MANDATORY_ID_SELL_AND_EAT => $langs->trans(
'BatchSellOrEatByMandatoryAll', $sellByLabel, $eatByLabel),
1670 $sellOrEatByMandatoryLabel =
'';
1673 if (isset($sellOrEatByMandatoryList[$this->sell_or_eat_by_mandatory])) {
1674 $sellOrEatByMandatoryLabel = $sellOrEatByMandatoryList[$this->sell_or_eat_by_mandatory];
1677 return $sellOrEatByMandatoryLabel;
1688 global $conf, $langs;
1690 $langs_available = $langs->get_available_languages(DOL_DOCUMENT_ROOT, 0, 2);
1691 $current_lang = $langs->getDefaultLang();
1693 foreach ($langs_available as $key => $value) {
1694 if ($key == $current_lang) {
1695 $sql =
"SELECT rowid";
1696 $sql .=
" FROM ".$this->db->prefix().
"product_lang";
1697 $sql .=
" WHERE fk_product = ".((int) $this->
id);
1698 $sql .=
" AND lang = '".$this->db->escape($key).
"'";
1700 $result = $this->db->query($sql);
1702 if ($this->db->num_rows($result)) {
1703 $sql2 =
"UPDATE ".$this->db->prefix().
"product_lang";
1705 $sql2 .=
" label='".$this->db->escape($this->label).
"',";
1706 $sql2 .=
" description='".$this->db->escape($this->
description).
"'";
1708 $sql2 .=
", note='".$this->db->escape($this->other).
"'";
1710 $sql2 .=
" WHERE fk_product = ".((int) $this->
id).
" AND lang = '".$this->db->escape($key).
"'";
1712 $sql2 =
"INSERT INTO ".$this->db->prefix().
"product_lang (fk_product, lang, label, description";
1717 $sql2 .=
" VALUES(".((int) $this->
id).
",'".$this->db->escape($key).
"','".$this->db->escape($this->label).
"',";
1718 $sql2 .=
" '".$this->db->escape($this->
description).
"'";
1720 $sql2 .=
", '".$this->db->escape($this->other).
"'";
1724 dol_syslog(get_class($this).
'::setMultiLangs key = current_lang = '.$key);
1725 if (!$this->db->query($sql2)) {
1726 $this->error = $this->db->lasterror();
1729 } elseif (isset($this->multilangs[$key])) {
1730 if (empty($this->multilangs[
"$key"][
"label"])) {
1731 $this->errors[] = $key .
' : ' . $langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv(
"Label"));
1735 $sql =
"SELECT rowid";
1736 $sql .=
" FROM ".$this->db->prefix().
"product_lang";
1737 $sql .=
" WHERE fk_product = ".((int) $this->
id);
1738 $sql .=
" AND lang = '".$this->db->escape($key).
"'";
1740 $result = $this->db->query($sql);
1742 if ($this->db->num_rows($result)) {
1743 $sql2 =
"UPDATE ".$this->db->prefix().
"product_lang";
1745 $sql2 .=
" label = '".$this->db->escape($this->multilangs[
"$key"][
"label"]).
"',";
1746 $sql2 .=
" description = '".$this->db->escape($this->multilangs[
"$key"][
"description"]).
"'";
1748 $sql2 .=
", note = '".$this->db->escape($this->multilangs[
"$key"][
"other"]).
"'";
1750 $sql2 .=
" WHERE fk_product = ".((int) $this->
id).
" AND lang = '".$this->db->escape($key).
"'";
1752 $sql2 =
"INSERT INTO ".$this->db->prefix().
"product_lang (fk_product, lang, label, description";
1757 $sql2 .=
" VALUES(".((int) $this->
id).
",'".$this->db->escape($key).
"','".$this->db->escape($this->multilangs[
"$key"][
"label"]).
"',";
1758 $sql2 .=
" '".$this->db->escape($this->multilangs[
"$key"][
"description"]).
"'";
1760 $sql2 .=
", '".$this->db->escape($this->multilangs[
"$key"][
"other"]).
"'";
1766 if ($this->multilangs[
"$key"][
"label"] || $this->multilangs[
"$key"][
"description"]) {
1767 if (!$this->db->query($sql2)) {
1768 $this->error = $this->db->lasterror();
1778 $result = $this->
call_trigger(
'PRODUCT_SET_MULTILANGS', $user);
1780 $this->error = $this->db->lasterror();
1798 $sql =
"DELETE FROM ".$this->db->prefix().
"product_lang";
1799 $sql .=
" WHERE fk_product = ".((int) $this->
id).
" AND lang = '".$this->db->escape($langtodelete).
"'";
1801 dol_syslog(get_class($this).
'::delMultiLangs', LOG_DEBUG);
1802 $result = $this->db->query($sql);
1805 $result = $this->
call_trigger(
'PRODUCT_DEL_MULTILANGS', $user);
1807 $this->error = $this->db->lasterror();
1808 dol_syslog(get_class($this).
'::delMultiLangs error='.$this->error, LOG_ERR);
1814 $this->error = $this->db->lasterror();
1815 dol_syslog(get_class($this).
'::delMultiLangs error='.$this->error, LOG_ERR);
1830 global $user, $langs, $conf;
1836 if ($type ==
'buy') {
1837 $field =
'accountancy_code_buy';
1838 } elseif ($type ==
'buy_intra') {
1839 $field =
'accountancy_code_buy_intra';
1840 } elseif ($type ==
'buy_export') {
1841 $field =
'accountancy_code_buy_export';
1842 } elseif ($type ==
'sell') {
1843 $field =
'accountancy_code_sell';
1844 } elseif ($type ==
'sell_intra') {
1845 $field =
'accountancy_code_sell_intra';
1846 } elseif ($type ==
'sell_export') {
1847 $field =
'accountancy_code_sell_export';
1852 $sql =
"UPDATE ".$this->db->prefix().$this->table_element.
" SET ";
1853 $sql .=
"$field = '".$this->db->escape($value).
"'";
1854 $sql .=
" WHERE rowid = ".((int) $this->
id);
1857 $resql = $this->db->query($sql);
1861 $result = $this->
call_trigger(
'PRODUCT_MODIFY', $user);
1868 $this->db->rollback();
1872 $this->$field = $value;
1874 $this->db->commit();
1877 $this->error = $this->db->lasterror();
1878 $this->db->rollback();
1892 $current_lang = $langs->getDefaultLang();
1894 $sql =
"SELECT lang, label, description, note as other";
1895 $sql .=
" FROM ".$this->db->prefix().
"product_lang";
1896 $sql .=
" WHERE fk_product = ".((int) $this->
id);
1898 $result = $this->db->query($sql);
1900 while ($obj = $this->db->fetch_object($result)) {
1902 if ($obj->lang == $current_lang) {
1903 $this->label = $obj->label;
1905 $this->other = $obj->other;
1907 $this->multilangs[(string) $obj->lang][
"label"] = $obj->label;
1908 $this->multilangs[(string) $obj->lang][
"description"] = $obj->description;
1909 $this->multilangs[(string) $obj->lang][
"other"] = $obj->other;
1913 $this->error =
"Error: ".$this->db->lasterror().
" - ".$sql;
1926 $testExit = array(
'multiprices',
'multiprices_ttc',
'multiprices_base_type',
'multiprices_min',
'multiprices_min_ttc',
'multiprices_tva_tx',
'multiprices_recuperableonly');
1928 foreach ($testExit as $field) {
1929 if (!isset($this->$field)) {
1932 $tmparray = $this->$field;
1933 if (!isset($tmparray[$level])) {
1939 'level' => $level ? $level : 1,
1940 'multiprices' => (float) $this->multiprices[$level],
1941 'multiprices_ttc' => (
float) $this->multiprices_ttc[$level],
1942 'multiprices_base_type' => $this->multiprices_base_type[$level],
1943 'multiprices_min' => (float) $this->multiprices_min[$level],
1944 'multiprices_min_ttc' => (
float) $this->multiprices_min_ttc[$level],
1945 'multiprices_tva_tx' => (float) $this->multiprices_tva_tx[$level],
1946 'multiprices_recuperableonly' => (
float) $this->multiprices_recuperableonly[$level],
1969 if (empty($this->price_by_qty)) {
1970 $this->price_by_qty = 0;
1974 $sql =
"INSERT INTO ".$this->db->prefix().
"product_price(price_level,date_price, fk_product, fk_user_author, price_label, price, price_ttc, price_base_type,tosell, tva_tx, default_vat_code, recuperableonly,";
1975 $sql .=
" localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, price_min,price_min_ttc,price_by_qty,entity,fk_price_expression) ";
1976 $sql .=
" VALUES(".($level ? ((int) $level) : 1).
", '".$this->db->idate($now).
"', ".((int) $this->
id).
", ".((int) $user->id).
", ".(empty($this->price_label) ?
"null" :
"'".$this->db->escape($this->price_label).
"'").
", ".((float)
price2num($this->
price)).
", ".((
float)
price2num($this->price_ttc)).
",'".$this->db->escape($this->price_base_type).
"',".((int) $this->
status).
", ".((float)
price2num($this->tva_tx)).
", ".($this->default_vat_code ? (
"'".$this->db->escape($this->default_vat_code).
"'") :
"null").
", ".((
int)
$this->tva_npr).
",";
1977 $sql .=
" ".price2num($this->localtax1_tx).
", ".
price2num($this->localtax2_tx).
", '".$this->db->escape($this->localtax1_type).
"', '".$this->db->escape($this->localtax2_type).
"', ".
price2num($this->price_min).
", ".
price2num($this->price_min_ttc).
", ".
price2num($this->price_by_qty).
", ".((int) $conf->entity).
",".($this->fk_price_expression > 0 ? ((int) $this->fk_price_expression) :
'null');
1980 dol_syslog(get_class($this).
"::_log_price", LOG_DEBUG);
1981 $resql = $this->db->query($sql);
1983 $this->error = $this->db->lasterror();
2003 $sql =
"DELETE FROM ".$this->db->prefix().
"product_price_by_qty";
2004 $sql .=
" WHERE fk_product_price = ".((int) $rowid);
2005 $resql = $this->db->query($sql);
2007 $sql =
"DELETE FROM ".$this->db->prefix().
"product_price";
2008 $sql .=
" WHERE rowid=".((int) $rowid);
2009 $resql = $this->db->query($sql);
2013 $this->error = $this->db->lasterror();
2028 public function getSellPrice($thirdparty_seller, $thirdparty_buyer, $pqp = 0)
2030 global $conf, $hookmanager, $action;
2033 if (is_object($hookmanager)) {
2034 $parameters = array(
'thirdparty_seller' => $thirdparty_seller,
'thirdparty_buyer' => $thirdparty_buyer,
'pqp' => $pqp);
2036 $reshook = $hookmanager->executeHooks(
'getSellPrice', $parameters, $this, $action);
2038 return $hookmanager->resArray;
2049 $pu_ht = $this->price;
2050 $pu_ttc = $this->price_ttc;
2051 $price_min = $this->price_min;
2052 $price_base_type = $this->price_base_type;
2055 if (
getDolGlobalString(
'PRODUIT_MULTIPRICES') && !empty($thirdparty_buyer->price_level)) {
2056 $pu_ht = $this->multiprices[$thirdparty_buyer->price_level];
2057 $pu_ttc = $this->multiprices_ttc[$thirdparty_buyer->price_level];
2058 $price_min = $this->multiprices_min[$thirdparty_buyer->price_level];
2059 $price_base_type = $this->multiprices_base_type[$thirdparty_buyer->price_level];
2061 if (isset($this->multiprices_tva_tx[$thirdparty_buyer->price_level])) {
2062 $tva_tx = $this->multiprices_tva_tx[$thirdparty_buyer->price_level];
2064 if (isset($this->multiprices_recuperableonly[$thirdparty_buyer->price_level])) {
2065 $tva_npr = $this->multiprices_recuperableonly[$thirdparty_buyer->price_level];
2073 require_once DOL_DOCUMENT_ROOT.
'/product/class/productcustomerprice.class.php';
2077 $filter = array(
't.fk_product' => $this->
id,
't.fk_soc' => $thirdparty_buyer->id);
2079 $result = $prodcustprice->fetchAll(
'',
'', 0, 0, $filter);
2081 if (count($prodcustprice->lines) > 0) {
2082 $pu_ht =
price($prodcustprice->lines[0]->price);
2083 $price_min =
price($prodcustprice->lines[0]->price_min);
2084 $pu_ttc =
price($prodcustprice->lines[0]->price_ttc);
2085 $price_base_type = $prodcustprice->lines[0]->price_base_type;
2086 $tva_tx = $prodcustprice->lines[0]->tva_tx;
2087 if ($prodcustprice->lines[0]->default_vat_code && !preg_match(
'/\(.*\)/',
$tva_tx)) {
2088 $tva_tx .=
' ('.$prodcustprice->lines[0]->default_vat_code.
')';
2090 $tva_npr = $prodcustprice->lines[0]->recuperableonly;
2098 if ($this->prices_by_qty[0]) {
2101 foreach ($this->prices_by_qty_list[0] as $priceforthequantityarray) {
2102 if ($priceforthequantityarray[
'rowid'] != $pqp) {
2106 if ($priceforthequantityarray[
'price_base_type'] ==
'HT') {
2107 $pu_ht = $priceforthequantityarray[
'unitprice'];
2109 $pu_ttc = $priceforthequantityarray[
'unitprice'];
2116 if ($this->prices_by_qty[$thirdparty_buyer->price_level]) {
2119 foreach ($this->prices_by_qty_list[$thirdparty_buyer->price_level] as $priceforthequantityarray) {
2120 if ($priceforthequantityarray[
'rowid'] != $pqp) {
2124 if ($priceforthequantityarray[
'price_base_type'] ==
'HT') {
2125 $pu_ht = $priceforthequantityarray[
'unitprice'];
2127 $pu_ttc = $priceforthequantityarray[
'unitprice'];
2134 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);
2151 public function get_buyprice($prodfournprice, $qty, $product_id = 0, $fourn_ref =
'', $fk_soc = 0)
2154 global $action, $hookmanager;
2157 if (is_object($hookmanager)) {
2158 $parameters = array(
2159 'prodfournprice' => $prodfournprice,
2161 'product_id' => $product_id,
2162 'fourn_ref' => $fourn_ref,
2163 'fk_soc' => $fk_soc,
2166 $reshook = $hookmanager->executeHooks(
'getBuyPrice', $parameters, $this, $action);
2168 return $hookmanager->resArray;
2175 $sql =
"SELECT pfp.rowid, pfp.price as price, pfp.quantity as quantity, pfp.remise_percent, pfp.fk_soc,";
2176 $sql .=
" pfp.fk_product, pfp.ref_fourn as ref_supplier, pfp.desc_fourn as desc_supplier, pfp.tva_tx, pfp.default_vat_code, pfp.fk_supplier_price_expression,";
2177 $sql .=
" pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code,";
2178 $sql .=
" pfp.packaging";
2179 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price as pfp";
2180 $sql .=
" WHERE pfp.rowid = ".((int) $prodfournprice);
2182 $sql .=
" AND pfp.quantity <= ".((float) $qty);
2184 $sql .=
" ORDER BY pfp.quantity DESC";
2186 dol_syslog(get_class($this).
"::get_buyprice first search by prodfournprice/qty", LOG_DEBUG);
2187 $resql = $this->db->query($sql);
2189 $obj = $this->db->fetch_object($resql);
2190 if ($obj && $obj->quantity > 0) {
2191 if (isModEnabled(
'dynamicprices') && !empty($obj->fk_supplier_price_expression)) {
2193 $prod_supplier->product_fourn_price_id = $obj->rowid;
2194 $prod_supplier->id = $obj->fk_product;
2195 $prod_supplier->fourn_qty = $obj->quantity;
2196 $prod_supplier->fourn_tva_tx = $obj->tva_tx;
2197 $prod_supplier->fk_supplier_price_expression = $obj->fk_supplier_price_expression;
2199 include_once DOL_DOCUMENT_ROOT.
'/product/dynamic_price/class/price_parser.class.php';
2201 $price_result = $priceparser->parseProductSupplier($prod_supplier);
2202 if ($price_result >= 0) {
2203 $obj->price = $price_result;
2206 $this->product_fourn_price_id = $obj->rowid;
2207 $this->buyprice = $obj->price;
2208 $this->fourn_pu = $obj->price / $obj->quantity;
2209 $this->fourn_price_base_type =
'HT';
2210 $this->fourn_socid = $obj->fk_soc;
2211 $this->ref_fourn = $obj->ref_supplier;
2212 $this->ref_supplier = $obj->ref_supplier;
2213 $this->desc_supplier = $obj->desc_supplier;
2214 $this->remise_percent = $obj->remise_percent;
2215 $this->vatrate_supplier = $obj->tva_tx;
2216 $this->default_vat_code_supplier = $obj->default_vat_code;
2217 $this->fourn_multicurrency_price = $obj->multicurrency_price;
2218 $this->fourn_multicurrency_unitprice = $obj->multicurrency_unitprice;
2219 $this->fourn_multicurrency_tx = $obj->multicurrency_tx;
2220 $this->fourn_multicurrency_id = $obj->fk_multicurrency;
2221 $this->fourn_multicurrency_code = $obj->multicurrency_code;
2223 $this->packaging = $obj->packaging;
2225 $result = $obj->fk_product;
2229 $sql =
"SELECT pfp.rowid, pfp.price as price, pfp.quantity as quantity, pfp.remise_percent, pfp.fk_soc,";
2230 $sql .=
" pfp.fk_product, pfp.ref_fourn as ref_supplier, pfp.desc_fourn as desc_supplier, pfp.tva_tx, pfp.default_vat_code, pfp.fk_supplier_price_expression,";
2231 $sql .=
" pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code,";
2232 $sql .=
" pfp.packaging";
2233 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price as pfp";
2234 $sql .=
" WHERE 1 = 1";
2235 if ($product_id > 0) {
2236 $sql .=
" AND pfp.fk_product = ".((int) $product_id);
2238 if ($fourn_ref !=
'none') {
2239 $sql .=
" AND pfp.ref_fourn = '".$this->db->escape($fourn_ref).
"'";
2242 $sql .=
" AND pfp.fk_soc = ".((int) $fk_soc);
2245 $sql .=
" AND pfp.quantity <= ".((float) $qty);
2247 $sql .=
" ORDER BY pfp.quantity DESC";
2250 dol_syslog(get_class($this).
"::get_buyprice second search from qty/ref/product_id", LOG_DEBUG);
2251 $resql = $this->db->query($sql);
2253 $obj = $this->db->fetch_object($resql);
2254 if ($obj && $obj->quantity > 0) {
2255 if (isModEnabled(
'dynamicprices') && !empty($obj->fk_supplier_price_expression)) {
2257 $prod_supplier->product_fourn_price_id = $obj->rowid;
2258 $prod_supplier->id = $obj->fk_product;
2259 $prod_supplier->fourn_qty = $obj->quantity;
2260 $prod_supplier->fourn_tva_tx = $obj->tva_tx;
2261 $prod_supplier->fk_supplier_price_expression = $obj->fk_supplier_price_expression;
2263 include_once DOL_DOCUMENT_ROOT.
'/product/dynamic_price/class/price_parser.class.php';
2265 $price_result = $priceparser->parseProductSupplier($prod_supplier);
2267 $obj->price = $price_result;
2270 $this->product_fourn_price_id = $obj->rowid;
2271 $this->buyprice = $obj->price;
2272 $this->fourn_qty = $obj->quantity;
2273 $this->fourn_pu = $obj->price / $obj->quantity;
2274 $this->fourn_price_base_type =
'HT';
2275 $this->fourn_socid = $obj->fk_soc;
2276 $this->ref_fourn = $obj->ref_supplier;
2277 $this->ref_supplier = $obj->ref_supplier;
2278 $this->desc_supplier = $obj->desc_supplier;
2279 $this->remise_percent = $obj->remise_percent;
2280 $this->vatrate_supplier = $obj->tva_tx;
2281 $this->default_vat_code_supplier = $obj->default_vat_code;
2282 $this->fourn_multicurrency_price = $obj->multicurrency_price;
2283 $this->fourn_multicurrency_unitprice = $obj->multicurrency_unitprice;
2284 $this->fourn_multicurrency_tx = $obj->multicurrency_tx;
2285 $this->fourn_multicurrency_id = $obj->fk_multicurrency;
2286 $this->fourn_multicurrency_code = $obj->multicurrency_code;
2288 $this->packaging = $obj->packaging;
2290 $result = $obj->fk_product;
2296 $this->error = $this->db->lasterror();
2301 $this->error = $this->db->lasterror();
2325 public function updatePrice($newprice, $newpricebase, $user, $newvat =
null, $newminprice = 0, $level = 0, $newnpr = 0, $newpbq = 0, $ignore_autogen = 0, $localtaxes_array = array(), $newdefaultvatcode =
'', $price_label =
'', $notrigger = 0)
2327 global $conf, $langs;
2333 dol_syslog(get_class($this).
"::update_price id=".$id.
" newprice=".$newprice.
" newpricebase=".$newpricebase.
" newminprice=".$newminprice.
" level=".$level.
" npr=".$newnpr.
" newdefaultvatcode=".$newdefaultvatcode);
2336 if (empty($this->tva_tx)) {
2339 if (empty($newnpr)) {
2342 if (empty($newminprice)) {
2347 if ($newvat ===
null || $newvat ==
'') {
2353 if ((
getDolGlobalString(
'PRODUIT_MULTIPRICES') ||
getDolGlobalString(
'PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) && !$ignore_autogen && $this->price_autogen && ($level == 1)) {
2354 return $this->
generateMultiprices($user, $newprice, $newpricebase, $newvat, $newnpr, $newpbq);
2357 if (!empty($newminprice) && ($newminprice > $newprice)) {
2358 $this->error =
'ErrorPriceCantBeLowerThanMinPrice';
2362 if ($newprice !==
'' || $newprice === 0) {
2363 if ($newpricebase ==
'TTC') {
2364 $price_ttc = (float)
price2num($newprice,
'MU');
2365 $price = (float)
price2num($newprice) / (1 + ((float) $newvat / 100));
2366 $price = (float)
price2num($price,
'MU');
2368 if ($newminprice !=
'' || $newminprice == 0) {
2369 $price_min_ttc = (float)
price2num($newminprice,
'MU');
2370 $price_min = (float)
price2num($newminprice) / (1 + ($newvat / 100));
2371 $price_min = (float)
price2num($price_min,
'MU');
2377 $price = (float)
price2num($newprice,
'MU');
2378 $price_ttc = ($newnpr != 1) ?
price2num($newprice) * (1 + ($newvat / 100)) : $price;
2379 $price_ttc = (float)
price2num($price_ttc,
'MU');
2381 if ($newminprice !==
'' || $newminprice === 0) {
2382 $price_min = (float)
price2num($newminprice,
'MU');
2383 $price_min_ttc = (float)
price2num($newminprice) * (1 + ($newvat / 100));
2384 $price_min_ttc = (float)
price2num($price_min_ttc,
'MU');
2393 if (count($localtaxes_array) > 0) {
2394 $localtaxtype1 = $localtaxes_array[
'0'];
2395 $localtax1 = $localtaxes_array[
'1'];
2396 $localtaxtype2 = $localtaxes_array[
'2'];
2397 $localtax2 = $localtaxes_array[
'3'];
2400 if (!empty($newdefaultvatcode)) {
2403 $sql =
"SELECT t.rowid, t.code, t.recuperableonly as tva_npr, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
2404 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_tva as t, ".MAIN_DB_PREFIX.
"c_country as c";
2405 $sql .=
" WHERE t.fk_pays = c.rowid AND c.code = '".$this->db->escape($mysoc->country_code).
"'";
2406 $sql .=
" AND t.taux = ".((float) $newdefaultvatcode).
" AND t.active = 1";
2407 $sql .=
" AND t.code = '".$this->db->escape($newdefaultvatcode).
"'";
2408 $resql = $this->db->query($sql);
2410 $obj = $this->db->fetch_object($resql);
2412 $npr = $obj->tva_npr;
2413 $localtax1 = $obj->localtax1;
2414 $localtax2 = $obj->localtax2;
2415 $localtaxtype1 = $obj->localtax1_type;
2416 $localtaxtype2 = $obj->localtax2_type;
2421 $localtaxtype1 =
'0';
2423 $localtaxtype2 =
'0';
2427 if (empty($localtax1)) {
2430 if (empty($localtax2)) {
2438 $sql =
"UPDATE ".$this->db->prefix().
"product SET";
2439 $sql .=
" price_base_type = '".$this->db->escape($newpricebase).
"',";
2440 $sql .=
" price = ".(float) $price.
",";
2441 $sql .=
" price_ttc = ".(float) $price_ttc.
",";
2442 $sql .=
" price_min = ".(float) $price_min.
",";
2443 $sql .=
" price_min_ttc = ".(float) $price_min_ttc.
",";
2444 $sql .=
" localtax1_tx = ".($localtax1 >= 0 ? (float) $localtax1 :
'NULL').
",";
2445 $sql .=
" localtax2_tx = ".($localtax2 >= 0 ? (float) $localtax2 :
'NULL').
",";
2446 $sql .=
" localtax1_type = ".($localtaxtype1 !=
'' ?
"'".$this->db->escape($localtaxtype1).
"'" :
"'0'").
",";
2447 $sql .=
" localtax2_type = ".($localtaxtype2 !=
'' ?
"'".$this->db->escape($localtaxtype2).
"'" :
"'0'").
",";
2448 $sql .=
" default_vat_code = ".($newdefaultvatcode ?
"'".$this->db->escape($newdefaultvatcode).
"'" :
"null").
",";
2449 $sql .=
" price_label = ".(!empty($price_label) ?
"'".$this->db->escape($price_label).
"'" :
"null").
",";
2450 $sql .=
" tva_tx = ".(float)
price2num($newvat).
",";
2451 $sql .=
" recuperableonly = '".$this->db->escape($newnpr).
"'";
2452 $sql .=
" WHERE rowid = ".((int) $id);
2454 dol_syslog(get_class($this).
"::update_price", LOG_DEBUG);
2455 $resql = $this->db->query($sql);
2457 $this->multiprices[$level] = $price;
2458 $this->multiprices_ttc[$level] = $price_ttc;
2459 $this->multiprices_min[$level] = $price_min;
2460 $this->multiprices_min_ttc[$level] = $price_min_ttc;
2461 $this->multiprices_base_type[$level] = $newpricebase;
2462 $this->multiprices_default_vat_code[$level] = $newdefaultvatcode;
2463 $this->multiprices_tva_tx[$level] = $newvat;
2464 $this->multiprices_recuperableonly[$level] = $newnpr;
2466 $this->
price = $price;
2467 $this->price_label = $price_label;
2468 $this->price_ttc = $price_ttc;
2469 $this->price_min = $price_min;
2470 $this->price_min_ttc = $price_min_ttc;
2471 $this->price_base_type = $newpricebase;
2472 $this->default_vat_code = $newdefaultvatcode;
2473 $this->tva_tx = $newvat;
2474 $this->tva_npr = $newnpr;
2477 $this->localtax1_tx = $localtax1;
2478 $this->localtax2_tx = $localtax2;
2479 $this->localtax1_type = $localtaxtype1;
2480 $this->localtax2_type = $localtaxtype2;
2483 $this->price_by_qty = $newpbq;
2487 if (!empty(array_diff_assoc($newPriceData, $lastPriceData)) || !
getDolGlobalString(
'PRODUIT_MULTIPRICES')) {
2491 $this->level = $level;
2495 $result = $this->
call_trigger(
'PRODUCT_PRICE_MODIFY', $user);
2497 $this->db->rollback();
2503 $this->db->commit();
2505 $this->db->rollback();
2506 $this->error = $this->db->lasterror();
2525 $this->fk_price_expression = $expression_id;
2527 return $this->
update($this->
id, $user);
2542 public function fetch($id = 0, $ref =
'', $ref_ext =
'', $barcode =
'', $ignore_expression = 0, $ignore_price_load = 0, $ignore_lang_load = 0)
2544 include_once DOL_DOCUMENT_ROOT.
'/core/lib/company.lib.php';
2546 global $langs, $conf;
2548 dol_syslog(get_class($this).
"::fetch id=".$id.
" ref=".$ref.
" ref_ext=".$ref_ext);
2551 if (!$id && !$ref && !$ref_ext && !$barcode) {
2552 $this->error =
'ErrorWrongParameters';
2553 dol_syslog(get_class($this).
"::fetch ".$this->error, LOG_ERR);
2557 $sql =
"SELECT p.rowid, p.ref, p.ref_ext, p.label, p.description, p.url, p.note_public, p.note as note_private, p.customcode, p.fk_country, p.fk_state, p.lifetime, p.qc_frequency, p.price, p.price_ttc,";
2558 $sql .=
" p.price_min, p.price_min_ttc, p.price_base_type, p.cost_price, p.default_vat_code, p.tva_tx, p.recuperableonly as tva_npr, p.localtax1_tx, p.localtax2_tx, p.localtax1_type, p.localtax2_type, p.tosell,";
2559 $sql .=
" p.tobuy, p.fk_product_type, p.duration, p.fk_default_warehouse, p.fk_default_workstation, p.seuil_stock_alerte, p.canvas, p.net_measure, p.net_measure_units, p.weight, p.weight_units,";
2560 $sql .=
" p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.last_main_doc,";
2561 $sql .=
" p.surface, p.surface_units, p.volume, p.volume_units, p.barcode, p.fk_barcode_type, p.finished, p.fk_default_bom, p.mandatory_period,";
2563 $sql .=
" p.accountancy_code_buy, p.accountancy_code_buy_intra, p.accountancy_code_buy_export, p.accountancy_code_sell, p.accountancy_code_sell_intra, p.accountancy_code_sell_export,";
2565 $sql .=
" ppe.accountancy_code_buy, ppe.accountancy_code_buy_intra, ppe.accountancy_code_buy_export, ppe.accountancy_code_sell, ppe.accountancy_code_sell_intra, ppe.accountancy_code_sell_export,";
2570 $separatedEntityPMP =
false;
2571 $separatedStock =
false;
2572 $visibleWarehousesEntities = $conf->entity;
2575 $checkPMPPerEntity = $this->db->query(
"SELECT pmp FROM " . $this->db->prefix() .
"product_perentity WHERE fk_product = ".((int) $id).
" AND entity = ".(
int) $conf->entity);
2576 if ($this->db->num_rows($checkPMPPerEntity) > 0) {
2577 $separatedEntityPMP =
true;
2581 $separatedStock =
true;
2582 if (isset($mc->sharings[
'stock']) && !empty($mc->sharings[
'stock'])) {
2583 $visibleWarehousesEntities .=
"," . implode(
",", $mc->sharings[
'stock']);
2586 if ($separatedEntityPMP) {
2587 $sql .=
" ppe.pmp,";
2591 $sql .=
" p.datec, p.tms, p.import_key, p.entity, p.desiredstock, p.tobatch, p.sell_or_eat_by_mandatory, p.batch_mask, p.fk_unit,";
2592 $sql .=
" p.fk_price_expression, p.price_autogen, p.model_pdf,";
2593 $sql .=
" p.price_label,";
2594 if ($separatedStock) {
2595 $sql .=
" SUM(sp.reel) as stock";
2599 $sql .=
" FROM ".$this->db->prefix().
"product as p";
2601 $sql .=
" LEFT JOIN " . $this->db->prefix() .
"product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity);
2603 if ($separatedStock) {
2604 $sql .=
" LEFT JOIN " . $this->db->prefix() .
"product_stock as sp ON sp.fk_product = p.rowid AND sp.fk_entrepot IN (SELECT rowid FROM ".$this->db->prefix().
"entrepot WHERE entity IN (".$this->db->sanitize($visibleWarehousesEntities).
"))";
2608 $sql .=
" WHERE p.rowid = ".((int) $id);
2610 $sql .=
" WHERE p.entity IN (".getEntity($this->element).
")";
2612 $sql .=
" AND p.ref = '".$this->db->escape($ref).
"'";
2613 } elseif ($ref_ext) {
2614 $sql .=
" AND p.ref_ext = '".$this->db->escape($ref_ext).
"'";
2615 } elseif ($barcode) {
2616 $sql .=
" AND p.barcode = '".$this->db->escape($barcode).
"'";
2619 if ($separatedStock) {
2620 $sql .=
" GROUP BY p.rowid, p.ref, p.ref_ext, p.label, p.description, p.url, p.note_public, p.note, p.customcode, p.fk_country, p.fk_state, p.lifetime, p.qc_frequency, p.price, p.price_ttc,";
2621 $sql .=
" p.price_min, p.price_min_ttc, p.price_base_type, p.cost_price, p.default_vat_code, p.tva_tx, p.recuperableonly, p.localtax1_tx, p.localtax2_tx, p.localtax1_type, p.localtax2_type, p.tosell,";
2622 $sql .=
" p.tobuy, p.fk_product_type, p.duration, p.fk_default_warehouse, p.fk_default_workstation, p.seuil_stock_alerte, p.canvas, p.net_measure, p.net_measure_units, p.weight, p.weight_units,";
2623 $sql .=
" p.length, p.length_units, p.width, p.width_units, p.height, p.height_units,";
2624 $sql .=
" p.surface, p.surface_units, p.volume, p.volume_units, p.barcode, p.fk_barcode_type, p.finished, p.fk_default_bom, p.mandatory_period,";
2626 $sql .=
" p.accountancy_code_buy, p.accountancy_code_buy_intra, p.accountancy_code_buy_export, p.accountancy_code_sell, p.accountancy_code_sell_intra, p.accountancy_code_sell_export,";
2628 $sql .=
" ppe.accountancy_code_buy, ppe.accountancy_code_buy_intra, ppe.accountancy_code_buy_export, ppe.accountancy_code_sell, ppe.accountancy_code_sell_intra, ppe.accountancy_code_sell_export,";
2630 if ($separatedEntityPMP) {
2631 $sql .=
" ppe.pmp,";
2635 $sql .=
" p.datec, p.tms, p.import_key, p.entity, p.desiredstock, p.tobatch, p.sell_or_eat_by_mandatory, p.batch_mask, p.fk_unit,";
2636 $sql .=
" p.fk_price_expression, p.price_autogen, p.model_pdf";
2637 $sql .=
" ,p.price_label";
2638 if (!$separatedStock) {
2639 $sql .=
", p.stock";
2643 $resql = $this->db->query($sql);
2645 unset($this->oldcopy);
2647 if ($this->db->num_rows($resql) > 0) {
2648 $obj = $this->db->fetch_object($resql);
2650 $this->
id = $obj->rowid;
2651 $this->
ref = $obj->ref;
2652 $this->ref_ext = $obj->ref_ext;
2653 $this->label = $obj->label;
2655 $this->url = $obj->url;
2656 $this->note_public = $obj->note_public;
2657 $this->note_private = $obj->note_private;
2658 $this->note = $obj->note_private;
2660 $this->
type = $obj->fk_product_type;
2661 $this->price_label = $obj->price_label;
2662 $this->
status = $obj->tosell;
2663 $this->status_buy = $obj->tobuy;
2664 $this->status_batch = $obj->tobatch;
2665 $this->sell_or_eat_by_mandatory = $obj->sell_or_eat_by_mandatory;
2666 $this->batch_mask = $obj->batch_mask;
2668 $this->customcode = $obj->customcode;
2669 $this->country_id = $obj->fk_country;
2670 $this->country_code =
getCountry($this->country_id, 2, $this->db);
2671 $this->state_id = $obj->fk_state;
2672 $this->lifetime = $obj->lifetime;
2673 $this->qc_frequency = $obj->qc_frequency;
2674 $this->
price = $obj->price;
2675 $this->price_ttc = $obj->price_ttc;
2676 $this->price_min = $obj->price_min;
2677 $this->price_min_ttc = $obj->price_min_ttc;
2678 $this->price_base_type = $obj->price_base_type;
2679 $this->cost_price = $obj->cost_price;
2680 $this->default_vat_code = $obj->default_vat_code;
2681 $this->tva_tx = $obj->tva_tx;
2683 $this->tva_npr = $obj->tva_npr;
2685 $this->localtax1_tx = $obj->localtax1_tx;
2686 $this->localtax2_tx = $obj->localtax2_tx;
2687 $this->localtax1_type = $obj->localtax1_type;
2688 $this->localtax2_type = $obj->localtax2_type;
2690 $this->finished = $obj->finished;
2691 $this->fk_default_bom = $obj->fk_default_bom;
2693 $this->duration = $obj->duration;
2694 $this->duration_value = $obj->duration ? (int) (substr($obj->duration, 0,
dol_strlen($obj->duration) - 1)) : 0;
2695 $this->duration_unit = $obj->duration ? substr($obj->duration, -1) :
null;
2696 $this->canvas = $obj->canvas;
2697 $this->net_measure = $obj->net_measure;
2698 $this->net_measure_units = $obj->net_measure_units;
2699 $this->weight = $obj->weight;
2700 $this->weight_units = (is_null($obj->weight_units) ? 0 : $obj->weight_units);
2701 $this->length = $obj->length;
2702 $this->length_units = (is_null($obj->length_units) ? 0 : $obj->length_units);
2703 $this->width = $obj->width;
2704 $this->width_units = (is_null($obj->width_units) ? 0 : $obj->width_units);
2705 $this->height = $obj->height;
2706 $this->height_units = (is_null($obj->height_units) ? 0 : $obj->height_units);
2708 $this->surface = $obj->surface;
2709 $this->surface_units = (is_null($obj->surface_units) ? 0 : $obj->surface_units);
2710 $this->volume = $obj->volume;
2711 $this->volume_units = (is_null($obj->volume_units) ? 0 : $obj->volume_units);
2712 $this->barcode = $obj->barcode;
2713 $this->barcode_type = $obj->fk_barcode_type;
2715 $this->accountancy_code_buy = $obj->accountancy_code_buy;
2716 $this->accountancy_code_buy_intra = $obj->accountancy_code_buy_intra;
2717 $this->accountancy_code_buy_export = $obj->accountancy_code_buy_export;
2718 $this->accountancy_code_sell = $obj->accountancy_code_sell;
2719 $this->accountancy_code_sell_intra = $obj->accountancy_code_sell_intra;
2720 $this->accountancy_code_sell_export = $obj->accountancy_code_sell_export;
2722 $this->fk_default_warehouse = $obj->fk_default_warehouse;
2723 $this->fk_default_workstation = $obj->fk_default_workstation;
2724 $this->seuil_stock_alerte = $obj->seuil_stock_alerte;
2725 $this->desiredstock = $obj->desiredstock;
2726 $this->stock_reel = $obj->stock;
2727 $this->pmp = $obj->pmp;
2729 $this->date_creation = $obj->datec;
2730 $this->date_modification = $obj->tms;
2731 $this->import_key = $obj->import_key;
2732 $this->entity = $obj->entity;
2734 $this->ref_ext = $obj->ref_ext;
2735 $this->fk_price_expression = $obj->fk_price_expression;
2736 $this->fk_unit = $obj->fk_unit;
2737 $this->price_autogen = $obj->price_autogen;
2738 $this->model_pdf = $obj->model_pdf;
2739 $this->last_main_doc = $obj->last_main_doc;
2741 $this->mandatory_period = $obj->mandatory_period;
2743 $this->db->free($resql);
2756 for ($i = 1; $i <= $maxi; $i++) {
2757 $sql =
"SELECT price, price_ttc, price_min, price_min_ttc,";
2758 $sql .=
" price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid, recuperableonly";
2759 $sql .=
" ,price_label";
2760 $sql .=
" FROM ".$this->db->prefix().
"product_price";
2761 $sql .=
" WHERE entity IN (".getEntity(
'productprice').
")";
2762 $sql .=
" AND price_level=".((int) $i);
2763 $sql .=
" AND fk_product = ".((int) $this->
id);
2764 $sql .=
" ORDER BY date_price DESC, rowid DESC";
2766 $resql = $this->db->query($sql);
2768 $result = $this->db->fetch_array($resql);
2770 $this->multiprices[$i] = $result ? $result[
"price"] :
null;
2771 $this->multiprices_ttc[$i] = $result ? $result[
"price_ttc"] :
null;
2772 $this->multiprices_min[$i] = $result ? $result[
"price_min"] :
null;
2773 $this->multiprices_min_ttc[$i] = $result ? $result[
"price_min_ttc"] :
null;
2774 $this->multiprices_base_type[$i] = $result ? $result[
"price_base_type"] :
null;
2776 $this->multiprices_tva_tx[$i] = $result ? $result[
"tva_tx"].($result ?
' ('.$result[
'default_vat_code'].
')' :
'') :
null;
2777 $this->multiprices_recuperableonly[$i] = $result ? $result[
"recuperableonly"] :
null;
2816 $this->error = $this->db->lasterror;
2820 } elseif (
getDolGlobalString(
'PRODUIT_CUSTOMER_PRICES') && empty($ignore_price_load)) {
2822 } elseif (
getDolGlobalString(
'PRODUIT_CUSTOMER_PRICES_BY_QTY') && empty($ignore_price_load)) {
2823 $sql =
"SELECT price, price_ttc, price_min, price_min_ttc,";
2824 $sql .=
" price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid";
2825 $sql .=
" FROM ".$this->db->prefix().
"product_price";
2826 $sql .=
" WHERE fk_product = ".((int) $this->
id);
2827 $sql .=
" ORDER BY date_price DESC, rowid DESC";
2830 $resql = $this->db->query($sql);
2832 $result = $this->db->fetch_array($resql);
2836 $this->prices_by_qty[0] = $result[
"price_by_qty"];
2837 $this->prices_by_qty_id[0] = $result[
"rowid"];
2839 if ($this->prices_by_qty[0] == 1) {
2840 $sql =
"SELECT rowid,price, unitprice, quantity, remise_percent, remise, remise, price_base_type";
2841 $sql .=
" FROM ".$this->db->prefix().
"product_price_by_qty";
2842 $sql .=
" WHERE fk_product_price = ".((int) $this->prices_by_qty_id[0]);
2843 $sql .=
" ORDER BY quantity ASC";
2845 $resql = $this->db->query($sql);
2847 $resultat = array();
2849 while ($result = $this->db->fetch_array($resql)) {
2850 $resultat[$ii] = array();
2851 $resultat[$ii][
"rowid"] = $result[
"rowid"];
2852 $resultat[$ii][
"price"] = $result[
"price"];
2853 $resultat[$ii][
"unitprice"] = $result[
"unitprice"];
2854 $resultat[$ii][
"quantity"] = $result[
"quantity"];
2855 $resultat[$ii][
"remise_percent"] = $result[
"remise_percent"];
2857 $resultat[$ii][
"price_base_type"] = $result[
"price_base_type"];
2860 $this->prices_by_qty_list[0] = $resultat;
2862 $this->error = $this->db->lasterror;
2868 $this->error = $this->db->lasterror;
2871 } elseif (
getDolGlobalString(
'PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') && empty($ignore_price_load)) {
2873 for ($i = 1; $i <= $maxi; $i++) {
2874 $sql =
"SELECT price, price_ttc, price_min, price_min_ttc,";
2875 $sql .=
" price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid, recuperableonly";
2876 $sql .=
" FROM ".$this->db->prefix().
"product_price";
2877 $sql .=
" WHERE entity IN (".getEntity(
'productprice').
")";
2878 $sql .=
" AND price_level=".((int) $i);
2879 $sql .=
" AND fk_product = ".((int) $this->
id);
2880 $sql .=
" ORDER BY date_price DESC, rowid DESC";
2882 $resql = $this->db->query($sql);
2884 $this->error = $this->db->lasterror;
2886 } elseif ($result = $this->db->fetch_array($resql)) {
2887 $this->multiprices[$i] = (!empty($result[
"price"]) ? $result[
"price"] : 0);
2888 $this->multiprices_ttc[$i] = (!empty($result[
"price_ttc"]) ? $result[
"price_ttc"] : 0);
2889 $this->multiprices_min[$i] = (!empty($result[
"price_min"]) ? $result[
"price_min"] : 0);
2890 $this->multiprices_min_ttc[$i] = (!empty($result[
"price_min_ttc"]) ? $result[
"price_min_ttc"] : 0);
2891 $this->multiprices_base_type[$i] = (!empty($result[
"price_base_type"]) ? $result[
"price_base_type"] :
'');
2893 $this->multiprices_tva_tx[$i] = (!empty($result[
"tva_tx"]) ? $result[
"tva_tx"] : 0);
2894 $this->multiprices_recuperableonly[$i] = (!empty($result[
"recuperableonly"]) ? $result[
"recuperableonly"] : 0);
2897 $this->prices_by_qty[$i] = (!empty($result[
"price_by_qty"]) ? $result[
"price_by_qty"] : 0);
2898 $this->prices_by_qty_id[$i] = (!empty($result[
"rowid"]) ? $result[
"rowid"] : 0);
2900 if ($this->prices_by_qty[$i] == 1) {
2901 $sql =
"SELECT rowid, price, unitprice, quantity, remise_percent, remise, price_base_type";
2902 $sql .=
" FROM ".$this->db->prefix().
"product_price_by_qty";
2903 $sql .=
" WHERE fk_product_price = ".((int) $this->prices_by_qty_id[$i]);
2904 $sql .=
" ORDER BY quantity ASC";
2906 $resql = $this->db->query($sql);
2908 $resultat = array();
2910 while ($result = $this->db->fetch_array($resql)) {
2911 $resultat[$ii] = array();
2912 $resultat[$ii][
"rowid"] = $result[
"rowid"];
2913 $resultat[$ii][
"price"] = $result[
"price"];
2914 $resultat[$ii][
"unitprice"] = $result[
"unitprice"];
2915 $resultat[$ii][
"quantity"] = $result[
"quantity"];
2916 $resultat[$ii][
"remise_percent"] = $result[
"remise_percent"];
2917 $resultat[$ii][
"remise"] = $result[
"remise"];
2918 $resultat[$ii][
"price_base_type"] = $result[
"price_base_type"];
2921 $this->prices_by_qty_list[$i] = $resultat;
2923 $this->error = $this->db->lasterror;
2931 if (isModEnabled(
'dynamicprices') && !empty($this->fk_price_expression) && empty($ignore_expression)) {
2932 include_once DOL_DOCUMENT_ROOT.
'/product/dynamic_price/class/price_parser.class.php';
2934 $price_result = $priceparser->parseProduct($this);
2935 if ($price_result >= 0) {
2936 $this->
price = $price_result;
2938 $this->price_ttc = (float)
price2num($this->
price) * (1 + ($this->tva_tx / 100));
2939 $this->price_ttc = (float)
price2num($this->price_ttc,
'MU');
2945 $this->stock_warehouse = array();
2952 $this->error = $this->db->lasterror();
2967 global $user, $hookmanager, $action;
2971 foreach (array(
'toconsume',
'consumed',
'toproduce',
'produced') as $role) {
2972 $this->stats_mo[
'customers_'.$role] = 0;
2973 $this->stats_mo[
'nb_'.$role] = 0;
2974 $this->stats_mo[
'qty_'.$role] = 0;
2976 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,";
2977 $sql .=
" SUM(mp.qty) as qty";
2978 $sql .=
" FROM ".$this->db->prefix().
"mrp_mo as c";
2979 $sql .=
" INNER JOIN ".$this->db->prefix().
"mrp_production as mp ON mp.fk_mo=c.rowid";
2980 if (!$user->hasRight(
'societe',
'client',
'voir')) {
2981 $sql .=
" INNER JOIN ".$this->db->prefix().
"societe_commerciaux as sc ON sc.fk_soc=c.fk_soc AND sc.fk_user = ".((int) $user->id);
2984 $sql .=
" c.entity IN (".getEntity(
'mo').
")";
2986 $sql .=
" AND mp.fk_product = ".((int) $this->
id);
2987 $sql .=
" AND mp.role ='".$this->db->escape($role).
"'";
2989 $sql .=
" AND c.fk_soc = ".((int) $socid);
2992 $result = $this->db->query($sql);
2994 $obj = $this->db->fetch_object($result);
2995 $this->stats_mo[
'customers_'.$role] = $obj->nb_customers ? $obj->nb_customers : 0;
2996 $this->stats_mo[
'nb_'.$role] = $obj->nb ? $obj->nb : 0;
2997 $this->stats_mo[
'qty_'.$role] = $obj->qty ?
price2num($obj->qty,
'MS') : 0;
2999 $this->error = $this->db->error();
3004 if (!empty($error)) {
3008 $parameters = array(
'socid' => $socid);
3009 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerMO', $parameters, $this, $action);
3011 $this->stats_mo = $hookmanager->resArray[
'stats_mo'];
3027 global $user, $hookmanager, $action;
3031 $this->stats_bom[
'nb_toproduce'] = 0;
3032 $this->stats_bom[
'nb_toconsume'] = 0;
3033 $this->stats_bom[
'qty_toproduce'] = 0;
3034 $this->stats_bom[
'qty_toconsume'] = 0;
3036 $sql =
"SELECT COUNT(DISTINCT b.rowid) as nb_toproduce,";
3037 $sql .=
" SUM(b.qty) as qty_toproduce";
3038 $sql .=
" FROM ".$this->db->prefix().
"bom_bom as b";
3039 $sql .=
" INNER JOIN ".$this->db->prefix().
"bom_bomline as bl ON bl.fk_bom=b.rowid";
3041 $sql .=
" b.entity IN (".getEntity(
'bom').
")";
3042 $sql .=
" AND b.fk_product =".((int) $this->
id);
3043 $sql .=
" GROUP BY b.rowid";
3045 $result = $this->db->query($sql);
3047 $obj = $this->db->fetch_object($result);
3048 $this->stats_bom[
'nb_toproduce'] = !empty($obj->nb_toproduce) ? $obj->nb_toproduce : 0;
3049 $this->stats_bom[
'qty_toproduce'] = !empty($obj->qty_toproduce) ?
price2num($obj->qty_toproduce) : 0;
3051 $this->error = $this->db->error();
3055 $sql =
"SELECT COUNT(DISTINCT bl.rowid) as nb_toconsume,";
3056 $sql .=
" SUM(bl.qty) as qty_toconsume";
3057 $sql .=
" FROM ".$this->db->prefix().
"bom_bom as b";
3058 $sql .=
" INNER JOIN ".$this->db->prefix().
"bom_bomline as bl ON bl.fk_bom=b.rowid";
3060 $sql .=
" b.entity IN (".getEntity(
'bom').
")";
3061 $sql .=
" AND bl.fk_product =".((int) $this->
id);
3063 $result = $this->db->query($sql);
3065 $obj = $this->db->fetch_object($result);
3066 $this->stats_bom[
'nb_toconsume'] = !empty($obj->nb_toconsume) ? $obj->nb_toconsume : 0;
3067 $this->stats_bom[
'qty_toconsume'] = !empty($obj->qty_toconsume) ?
price2num($obj->qty_toconsume) : 0;
3069 $this->error = $this->db->error();
3073 if (!empty($error)) {
3077 $parameters = array(
'socid' => $socid);
3078 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerMO', $parameters, $this, $action);
3080 $this->stats_bom = $hookmanager->resArray[
'stats_bom'];
3096 global $conf, $user, $hookmanager, $action;
3098 $sql =
"SELECT COUNT(DISTINCT p.fk_soc) as nb_customers, COUNT(DISTINCT p.rowid) as nb,";
3099 $sql .=
" COUNT(pd.rowid) as nb_rows, SUM(pd.qty) as qty";
3100 $sql .=
" FROM ".$this->db->prefix().
"propaldet as pd";
3101 $sql .=
", ".$this->db->prefix().
"propal as p";
3102 $sql .=
", ".$this->db->prefix().
"societe as s";
3103 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3104 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3106 $sql .=
" WHERE p.rowid = pd.fk_propal";
3107 $sql .=
" AND p.fk_soc = s.rowid";
3108 $sql .=
" AND p.entity IN (".getEntity(
'propal').
")";
3109 $sql .=
" AND pd.fk_product = ".((int) $this->
id);
3110 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3111 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3115 $sql .=
" AND p.fk_soc = ".((int) $socid);
3118 $result = $this->db->query($sql);
3120 $obj = $this->db->fetch_object($result);
3121 $this->stats_propale[
'customers'] = $obj->nb_customers;
3122 $this->stats_propale[
'nb'] = $obj->nb;
3123 $this->stats_propale[
'rows'] = $obj->nb_rows;
3124 $this->stats_propale[
'qty'] = $obj->qty ? $obj->qty : 0;
3129 if (is_array($TFather) && !empty($TFather)) {
3130 foreach ($TFather as &$fatherData) {
3131 $pFather =
new Product($this->db);
3132 $pFather->id = $fatherData[
'id'];
3133 $qtyCoef = $fatherData[
'qty'];
3135 if ($fatherData[
'incdec']) {
3136 $pFather->load_stats_propale($socid);
3138 $this->stats_propale[
'customers'] += $pFather->stats_propale[
'customers'];
3139 $this->stats_propale[
'nb'] += $pFather->stats_propale[
'nb'];
3140 $this->stats_propale[
'rows'] += $pFather->stats_propale[
'rows'];
3141 $this->stats_propale[
'qty'] += $pFather->stats_propale[
'qty'] * $qtyCoef;
3147 $parameters = array(
'socid' => $socid);
3148 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerProposal', $parameters, $this, $action);
3150 $this->stats_propale = $hookmanager->resArray[
'stats_propale'];
3155 $this->error = $this->db->error();
3171 global $conf, $user, $hookmanager, $action;
3173 $sql =
"SELECT COUNT(DISTINCT p.fk_soc) as nb_suppliers, COUNT(DISTINCT p.rowid) as nb,";
3174 $sql .=
" COUNT(pd.rowid) as nb_rows, SUM(pd.qty) as qty";
3175 $sql .=
" FROM ".$this->db->prefix().
"supplier_proposaldet as pd";
3176 $sql .=
", ".$this->db->prefix().
"supplier_proposal as p";
3177 $sql .=
", ".$this->db->prefix().
"societe as s";
3178 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3179 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3181 $sql .=
" WHERE p.rowid = pd.fk_supplier_proposal";
3182 $sql .=
" AND p.fk_soc = s.rowid";
3183 $sql .=
" AND p.entity IN (".getEntity(
'supplier_proposal').
")";
3184 $sql .=
" AND pd.fk_product = ".((int) $this->
id);
3185 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3186 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3190 $sql .=
" AND p.fk_soc = ".((int) $socid);
3193 $result = $this->db->query($sql);
3195 $obj = $this->db->fetch_object($result);
3196 $this->stats_proposal_supplier[
'suppliers'] = $obj->nb_suppliers;
3197 $this->stats_proposal_supplier[
'nb'] = $obj->nb;
3198 $this->stats_proposal_supplier[
'rows'] = $obj->nb_rows;
3199 $this->stats_proposal_supplier[
'qty'] = $obj->qty ? $obj->qty : 0;
3201 $parameters = array(
'socid' => $socid);
3202 $reshook = $hookmanager->executeHooks(
'loadStatsSupplierProposal', $parameters, $this, $action);
3204 $this->stats_proposal_supplier = $hookmanager->resArray[
'stats_proposal_supplier'];
3209 $this->error = $this->db->error();
3227 global $conf, $user, $hookmanager, $action;
3229 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,";
3230 $sql .=
" COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty";
3231 $sql .=
" FROM ".$this->db->prefix().
"commandedet as cd";
3232 $sql .=
", ".$this->db->prefix().
"commande as c";
3233 $sql .=
", ".$this->db->prefix().
"societe as s";
3234 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3235 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3237 $sql .=
" WHERE c.rowid = cd.fk_commande";
3238 $sql .=
" AND c.fk_soc = s.rowid";
3239 $sql .=
" AND c.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'commande').
")";
3240 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
3241 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3242 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3245 $sql .=
" AND c.fk_soc = ".((int) $socid);
3247 if ($filtrestatut !=
'') {
3248 $sql .=
" AND c.fk_statut in (".$this->db->sanitize($filtrestatut).
")";
3251 $result = $this->db->query($sql);
3253 $obj = $this->db->fetch_object($result);
3254 $this->stats_commande[
'customers'] = $obj->nb_customers;
3255 $this->stats_commande[
'nb'] = $obj->nb;
3256 $this->stats_commande[
'rows'] = $obj->nb_rows;
3257 $this->stats_commande[
'qty'] = $obj->qty ? $obj->qty : 0;
3262 if (is_array($TFather) && !empty($TFather)) {
3263 foreach ($TFather as &$fatherData) {
3264 $pFather =
new Product($this->db);
3265 $pFather->id = $fatherData[
'id'];
3266 $qtyCoef = $fatherData[
'qty'];
3268 if ($fatherData[
'incdec']) {
3269 $pFather->load_stats_commande($socid, $filtrestatut);
3271 $this->stats_commande[
'customers'] += $pFather->stats_commande[
'customers'];
3272 $this->stats_commande[
'nb'] += $pFather->stats_commande[
'nb'];
3273 $this->stats_commande[
'rows'] += $pFather->stats_commande[
'rows'];
3274 $this->stats_commande[
'qty'] += $pFather->stats_commande[
'qty'] * $qtyCoef;
3286 $sql =
"SELECT SUM(".$this->db->ifsql(
'f.type=2', -1, 1).
" * fd.qty) as count FROM ".$this->db->prefix().
"facturedet as fd ";
3287 $sql .=
" JOIN ".$this->db->prefix().
"facture as f ON fd.fk_facture = f.rowid";
3288 $sql .=
" JOIN ".$this->db->prefix().
"element_element as el ON ((el.fk_target = f.rowid AND el.targettype = 'facture' AND sourcetype = 'commande') OR (el.fk_source = f.rowid AND el.targettype = 'commande' AND sourcetype = 'facture'))";
3289 $sql .=
" JOIN ".$this->db->prefix().
"commande as c ON el.fk_source = c.rowid";
3290 $sql .=
" WHERE c.fk_statut IN (".$this->db->sanitize($filtrestatut).
") AND c.facture = 0 AND fd.fk_product = ".((int) $this->
id);
3292 dol_syslog(__METHOD__.
":: sql $sql", LOG_NOTICE);
3293 $resql = $this->db->query($sql);
3295 if ($this->db->num_rows($resql) > 0) {
3296 $obj = $this->db->fetch_object($resql);
3297 $adeduire += $obj->count;
3301 $this->stats_commande[
'qty'] -= $adeduire;
3304 include_once DOL_DOCUMENT_ROOT.
'/compta/facture/class/facture.class.php';
3308 $sql =
"SELECT sum(".$this->db->ifsql(
'f.type=2', -1, 1).
" * fd.qty) as count FROM ".MAIN_DB_PREFIX.
"facturedet as fd ";
3309 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"facture as f ON fd.fk_facture = f.rowid";
3310 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"element_element as el ON ((el.fk_target = f.rowid AND el.targettype = 'facture' AND sourcetype = 'commande') OR (el.fk_source = f.rowid AND el.targettype = 'commande' AND sourcetype = 'facture'))";
3311 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"commande as c ON el.fk_source = c.rowid";
3312 $sql .=
" WHERE c.fk_statut IN (".$this->db->sanitize($filtrestatut).
") AND f.fk_statut > ".
Facture::STATUS_DRAFT.
" AND fd.fk_product = ".((int) $this->
id);
3314 dol_syslog(__METHOD__.
":: sql $sql", LOG_NOTICE);
3315 $resql = $this->db->query($sql);
3317 if ($this->db->num_rows($resql) > 0) {
3318 $obj = $this->db->fetch_object($resql);
3319 $adeduire += $obj->count;
3322 $this->error = $this->db->error();
3326 $this->stats_commande[
'qty'] -= $adeduire;
3330 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3331 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerOrder', $parameters, $this, $action);
3333 $this->stats_commande = $hookmanager->resArray[
'stats_commande'];
3337 $this->error = $this->db->error();
3355 global $conf, $user, $hookmanager, $action;
3357 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_suppliers, COUNT(DISTINCT c.rowid) as nb,";
3358 $sql .=
" COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty";
3359 $sql .=
" FROM ".$this->db->prefix().
"commande_fournisseurdet as cd";
3360 $sql .=
", ".$this->db->prefix().
"commande_fournisseur as c";
3361 $sql .=
", ".$this->db->prefix().
"societe as s";
3362 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3363 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3365 $sql .=
" WHERE c.rowid = cd.fk_commande";
3366 $sql .=
" AND c.fk_soc = s.rowid";
3367 $sql .=
" AND c.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'supplier_order').
")";
3368 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
3369 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3370 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3373 $sql .=
" AND c.fk_soc = ".((int) $socid);
3375 if ($filtrestatut !=
'') {
3376 $sql .=
" AND c.fk_statut in (".$this->db->sanitize($filtrestatut).
")";
3378 if (!empty($dateofvirtualstock)) {
3379 $sql .=
" AND c.date_livraison <= '".$this->db->idate($dateofvirtualstock).
"'";
3382 $result = $this->db->query($sql);
3384 $obj = $this->db->fetch_object($result);
3385 $this->stats_commande_fournisseur[
'suppliers'] = $obj->nb_suppliers;
3386 $this->stats_commande_fournisseur[
'nb'] = $obj->nb;
3387 $this->stats_commande_fournisseur[
'rows'] = $obj->nb_rows;
3388 $this->stats_commande_fournisseur[
'qty'] = $obj->qty ? $obj->qty : 0;
3390 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3391 $reshook = $hookmanager->executeHooks(
'loadStatsSupplierOrder', $parameters, $this, $action);
3393 $this->stats_commande_fournisseur = $hookmanager->resArray[
'stats_commande_fournisseur'];
3398 $this->error = $this->db->error().
' sql='.$sql;
3413 public function load_stats_sending($socid = 0, $filtrestatut =
'', $forVirtualStock = 0, $filterShipmentStatus =
'')
3416 global $conf, $user, $hookmanager, $action;
3418 $sql =
"SELECT COUNT(DISTINCT e.fk_soc) as nb_customers, COUNT(DISTINCT e.rowid) as nb,";
3419 $sql .=
" COUNT(ed.rowid) as nb_rows, SUM(ed.qty) as qty";
3420 $sql .=
" FROM ".$this->db->prefix().
"expeditiondet as ed";
3421 $sql .=
", ".$this->db->prefix().
"commandedet as cd";
3422 $sql .=
", ".$this->db->prefix().
"commande as c";
3423 $sql .=
", ".$this->db->prefix().
"expedition as e";
3424 $sql .=
", ".$this->db->prefix().
"societe as s";
3425 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3426 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3428 $sql .=
" WHERE e.rowid = ed.fk_expedition";
3429 $sql .=
" AND c.rowid = cd.fk_commande";
3430 $sql .=
" AND e.fk_soc = s.rowid";
3431 $sql .=
" AND e.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'expedition').
")";
3432 $sql .=
" AND ed.fk_elementdet = cd.rowid";
3433 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
3434 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3435 $sql .=
" AND e.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3438 $sql .=
" AND e.fk_soc = ".((int) $socid);
3440 if ($filtrestatut !=
'') {
3441 $sql .=
" AND c.fk_statut IN (".$this->db->sanitize($filtrestatut).
")";
3443 if (!empty($filterShipmentStatus)) {
3444 $sql .=
" AND e.fk_statut IN (".$this->db->sanitize($filterShipmentStatus).
")";
3447 $result = $this->db->query($sql);
3449 $obj = $this->db->fetch_object($result);
3450 $this->stats_expedition[
'customers'] = $obj->nb_customers;
3451 $this->stats_expedition[
'nb'] = $obj->nb;
3452 $this->stats_expedition[
'rows'] = $obj->nb_rows;
3453 $this->stats_expedition[
'qty'] = $obj->qty ? $obj->qty : 0;
3458 if (is_array($TFather) && !empty($TFather)) {
3459 foreach ($TFather as &$fatherData) {
3460 $pFather =
new Product($this->db);
3461 $pFather->id = $fatherData[
'id'];
3462 $qtyCoef = $fatherData[
'qty'];
3464 if ($fatherData[
'incdec']) {
3465 $pFather->load_stats_sending($socid, $filtrestatut, $forVirtualStock);
3467 $this->stats_expedition[
'customers'] += $pFather->stats_expedition[
'customers'];
3468 $this->stats_expedition[
'nb'] += $pFather->stats_expedition[
'nb'];
3469 $this->stats_expedition[
'rows'] += $pFather->stats_expedition[
'rows'];
3470 $this->stats_expedition[
'qty'] += $pFather->stats_expedition[
'qty'] * $qtyCoef;
3476 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock,
'filterShipmentStatus' => $filterShipmentStatus);
3477 $reshook = $hookmanager->executeHooks(
'loadStatsSending', $parameters, $this, $action);
3479 $this->stats_expedition = $hookmanager->resArray[
'stats_expedition'];
3484 $this->error = $this->db->error();
3499 public function load_stats_reception($socid = 0, $filtrestatut =
'', $forVirtualStock = 0, $dateofvirtualstock =
null)
3502 global $conf, $user, $hookmanager, $action;
3504 $sql =
"SELECT COUNT(DISTINCT cf.fk_soc) as nb_suppliers, COUNT(DISTINCT cf.rowid) as nb,";
3505 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(fd.qty) as qty";
3506 $sql .=
" FROM ".$this->db->prefix().
"receptiondet_batch as fd";
3507 $sql .=
", ".$this->db->prefix().
"commande_fournisseur as cf";
3508 $sql .=
", ".$this->db->prefix().
"societe as s";
3509 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3510 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3512 $sql .=
" WHERE cf.rowid = fd.fk_element";
3513 $sql .=
" AND cf.fk_soc = s.rowid";
3514 $sql .=
" AND cf.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'supplier_order').
")";
3515 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
3516 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3517 $sql .=
" AND cf.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3520 $sql .=
" AND cf.fk_soc = ".((int) $socid);
3522 if ($filtrestatut !=
'') {
3523 $sql .=
" AND cf.fk_statut IN (".$this->db->sanitize($filtrestatut).
")";
3525 if (!empty($dateofvirtualstock)) {
3526 $sql .=
" AND fd.datec <= '".$this->db->idate($dateofvirtualstock).
"'";
3529 $result = $this->db->query($sql);
3531 $obj = $this->db->fetch_object($result);
3532 $this->stats_reception[
'suppliers'] = $obj->nb_suppliers;
3533 $this->stats_reception[
'nb'] = $obj->nb;
3534 $this->stats_reception[
'rows'] = $obj->nb_rows;
3535 $this->stats_reception[
'qty'] = $obj->qty ? $obj->qty : 0;
3537 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3538 $reshook = $hookmanager->executeHooks(
'loadStatsReception', $parameters, $this, $action);
3540 $this->stats_reception = $hookmanager->resArray[
'stats_reception'];
3545 $this->error = $this->db->error();
3561 public function load_stats_inproduction($socid = 0, $filtrestatut =
'', $forVirtualStock = 0, $dateofvirtualstock =
null, $warehouseid = 0)
3564 global $user, $hookmanager, $action;
3566 $serviceStockIsEnabled = isModEnabled(
"service") &&
getDolGlobalString(
'STOCK_SUPPORTS_SERVICES');
3568 $sql =
"SELECT COUNT(DISTINCT m.fk_soc) as nb_customers, COUNT(DISTINCT m.rowid) as nb,";
3569 $sql .=
" COUNT(mp.rowid) as nb_rows, SUM(mp.qty) as qty, role";
3570 $sql .=
" FROM ".$this->db->prefix().
"mrp_production as mp";
3571 $sql .=
", ".$this->db->prefix().
"mrp_mo as m";
3572 $sql .=
" LEFT JOIN ".$this->db->prefix().
"societe as s ON s.rowid = m.fk_soc";
3573 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3574 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3576 $sql .=
" WHERE m.rowid = mp.fk_mo";
3577 $sql .=
" AND m.entity IN (".getEntity(($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE')) ?
'stock' :
'mrp').
")";
3578 $sql .=
" AND mp.fk_product = ".((int) $this->
id);
3579 $sql .=
" AND (mp.disable_stock_change IN (0) OR mp.disable_stock_change IS NULL)";
3580 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3581 $sql .=
" AND m.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3584 $sql .=
" AND m.fk_soc = ".((int) $socid);
3586 if ($filtrestatut !=
'') {
3587 $sql .=
" AND m.status IN (".$this->db->sanitize($filtrestatut).
")";
3589 if (!empty($dateofvirtualstock)) {
3590 $sql .=
" AND m.date_valid <= '".$this->db->idate($dateofvirtualstock).
"'";
3592 if (!$serviceStockIsEnabled) {
3593 $sql .=
"AND EXISTS (SELECT p.rowid FROM ".$this->db->prefix().
"product AS p WHERE p.rowid = ".((int) $this->
id).
" AND p.fk_product_type IN (0))";
3595 if (!empty($warehouseid)) {
3596 $sql .=
" AND m.fk_warehouse = ".((int) $warehouseid);
3598 $sql .=
" GROUP BY role";
3601 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] = 0;
3603 $this->stats_mrptoconsume[
'customers'] = 0;
3604 $this->stats_mrptoconsume[
'nb'] = 0;
3605 $this->stats_mrptoconsume[
'rows'] = 0;
3606 $this->stats_mrptoconsume[
'qty'] = 0;
3607 $this->stats_mrptoproduce[
'customers'] = 0;
3608 $this->stats_mrptoproduce[
'nb'] = 0;
3609 $this->stats_mrptoproduce[
'rows'] = 0;
3610 $this->stats_mrptoproduce[
'qty'] = 0;
3613 $result = $this->db->query($sql);
3615 while ($obj = $this->db->fetch_object($result)) {
3616 if ($obj->role ==
'toconsume' && empty($warehouseid)) {
3617 $this->stats_mrptoconsume[
'customers'] += $obj->nb_customers;
3618 $this->stats_mrptoconsume[
'nb'] += $obj->nb;
3619 $this->stats_mrptoconsume[
'rows'] += $obj->nb_rows;
3620 $this->stats_mrptoconsume[
'qty'] += ($obj->qty ? $obj->qty : 0);
3622 if ($obj->role ==
'consumed' && empty($warehouseid)) {
3626 $this->stats_mrptoconsume[
'qty'] -= ($obj->qty ? $obj->qty : 0);
3628 if ($obj->role ==
'toproduce') {
3630 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] += ($obj->qty ? $obj->qty : 0);
3632 $this->stats_mrptoproduce[
'customers'] += $obj->nb_customers;
3633 $this->stats_mrptoproduce[
'nb'] += $obj->nb;
3634 $this->stats_mrptoproduce[
'rows'] += $obj->nb_rows;
3635 $this->stats_mrptoproduce[
'qty'] += ($obj->qty ? $obj->qty : 0);
3638 if ($obj->role ==
'produced') {
3643 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] -= ($obj->qty ? $obj->qty : 0);
3645 $this->stats_mrptoproduce[
'qty'] -= ($obj->qty ? $obj->qty : 0);
3652 if ($this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] < 0) {
3653 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] = 0;
3656 if ($this->stats_mrptoconsume[
'qty'] < 0) {
3657 $this->stats_mrptoconsume[
'qty'] = 0;
3659 if ($this->stats_mrptoproduce[
'qty'] < 0) {
3660 $this->stats_mrptoproduce[
'qty'] = 0;
3664 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3665 $reshook = $hookmanager->executeHooks(
'loadStatsInProduction', $parameters, $this, $action);
3667 $this->stats_mrptoproduce = $hookmanager->resArray[
'stats_mrptoproduce'];
3672 $this->error = $this->db->error();
3687 global $conf, $user, $hookmanager, $action;
3689 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,";
3690 $sql .=
" COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty";
3691 $sql .=
" FROM ".$this->db->prefix().
"contratdet as cd";
3692 $sql .=
", ".$this->db->prefix().
"contrat as c";
3693 $sql .=
", ".$this->db->prefix().
"societe as s";
3694 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3695 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3697 $sql .=
" WHERE c.rowid = cd.fk_contrat";
3698 $sql .=
" AND c.fk_soc = s.rowid";
3699 $sql .=
" AND c.entity IN (".getEntity(
'contract').
")";
3700 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
3701 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3702 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3706 $sql .=
" AND c.fk_soc = ".((int) $socid);
3709 $result = $this->db->query($sql);
3711 $obj = $this->db->fetch_object($result);
3712 $this->stats_contrat[
'customers'] = $obj->nb_customers;
3713 $this->stats_contrat[
'nb'] = $obj->nb;
3714 $this->stats_contrat[
'rows'] = $obj->nb_rows;
3715 $this->stats_contrat[
'qty'] = $obj->qty ? $obj->qty : 0;
3720 if (is_array($TFather) && !empty($TFather)) {
3721 foreach ($TFather as &$fatherData) {
3722 $pFather =
new Product($this->db);
3723 $pFather->id = $fatherData[
'id'];
3724 $qtyCoef = $fatherData[
'qty'];
3726 if ($fatherData[
'incdec']) {
3727 $pFather->load_stats_contrat($socid);
3729 $this->stats_contrat[
'customers'] += $pFather->stats_contrat[
'customers'];
3730 $this->stats_contrat[
'nb'] += $pFather->stats_contrat[
'nb'];
3731 $this->stats_contrat[
'rows'] += $pFather->stats_contrat[
'rows'];
3732 $this->stats_contrat[
'qty'] += $pFather->stats_contrat[
'qty'] * $qtyCoef;
3738 $parameters = array(
'socid' => $socid);
3739 $reshook = $hookmanager->executeHooks(
'loadStatsContract', $parameters, $this, $action);
3741 $this->stats_contrat = $hookmanager->resArray[
'stats_contrat'];
3746 $this->error = $this->db->error().
' sql='.$sql;
3761 global $conf, $user, $hookmanager, $action;
3763 $sql =
"SELECT COUNT(DISTINCT f.fk_soc) as nb_customers, COUNT(DISTINCT f.rowid) as nb,";
3764 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(".$this->db->ifsql(
'f.type != 2',
'fd.qty',
'fd.qty * -1').
") as qty";
3765 $sql .=
" FROM ".$this->db->prefix().
"facturedet as fd";
3766 $sql .=
", ".$this->db->prefix().
"facture as f";
3767 $sql .=
", ".$this->db->prefix().
"societe as s";
3768 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3769 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3771 $sql .=
" WHERE f.rowid = fd.fk_facture";
3772 $sql .=
" AND f.fk_soc = s.rowid";
3773 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
3774 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
3775 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3776 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3780 $sql .=
" AND f.fk_soc = ".((int) $socid);
3783 $result = $this->db->query($sql);
3785 $obj = $this->db->fetch_object($result);
3786 $this->stats_facture[
'customers'] = $obj->nb_customers;
3787 $this->stats_facture[
'nb'] = $obj->nb;
3788 $this->stats_facture[
'rows'] = $obj->nb_rows;
3789 $this->stats_facture[
'qty'] = $obj->qty ? $obj->qty : 0;
3794 if (is_array($TFather) && !empty($TFather)) {
3795 foreach ($TFather as &$fatherData) {
3796 $pFather =
new Product($this->db);
3797 $pFather->id = $fatherData[
'id'];
3798 $qtyCoef = $fatherData[
'qty'];
3800 if ($fatherData[
'incdec']) {
3801 $pFather->load_stats_facture($socid);
3803 $this->stats_facture[
'customers'] += $pFather->stats_facture[
'customers'];
3804 $this->stats_facture[
'nb'] += $pFather->stats_facture[
'nb'];
3805 $this->stats_facture[
'rows'] += $pFather->stats_facture[
'rows'];
3806 $this->stats_facture[
'qty'] += $pFather->stats_facture[
'qty'] * $qtyCoef;
3812 $parameters = array(
'socid' => $socid);
3813 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerInvoice', $parameters, $this, $action);
3815 $this->stats_facture = $hookmanager->resArray[
'stats_facture'];
3820 $this->error = $this->db->error();
3836 global $conf, $user, $hookmanager, $action;
3838 $sql =
"SELECT COUNT(DISTINCT f.fk_soc) as nb_customers, COUNT(DISTINCT f.rowid) as nb,";
3839 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(fd.qty) as qty";
3840 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facturedet_rec as fd";
3841 $sql .=
", ".MAIN_DB_PREFIX.
"facture_rec as f";
3842 $sql .=
", ".MAIN_DB_PREFIX.
"societe as s";
3843 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3844 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
3846 $sql .=
" WHERE f.rowid = fd.fk_facture";
3847 $sql .=
" AND f.fk_soc = s.rowid";
3848 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
3849 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
3850 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3851 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3855 $sql .=
" AND f.fk_soc = ".((int) $socid);
3858 $result = $this->db->query($sql);
3860 $obj = $this->db->fetch_object($result);
3861 $this->stats_facturerec[
'customers'] = $obj->nb_customers;
3862 $this->stats_facturerec[
'nb'] = $obj->nb;
3863 $this->stats_facturerec[
'rows'] = $obj->nb_rows;
3864 $this->stats_facturerec[
'qty'] = $obj->qty ? $obj->qty : 0;
3869 if (is_array($TFather) && !empty($TFather)) {
3870 foreach ($TFather as &$fatherData) {
3871 $pFather =
new Product($this->db);
3872 $pFather->id = $fatherData[
'id'];
3873 $qtyCoef = $fatherData[
'qty'];
3875 if ($fatherData[
'incdec']) {
3876 $pFather->load_stats_facture($socid);
3878 $this->stats_facturerec[
'customers'] += $pFather->stats_facturerec[
'customers'];
3879 $this->stats_facturerec[
'nb'] += $pFather->stats_facturerec[
'nb'];
3880 $this->stats_facturerec[
'rows'] += $pFather->stats_facturerec[
'rows'];
3881 $this->stats_facturerec[
'qty'] += $pFather->stats_facturerec[
'qty'] * $qtyCoef;
3887 $parameters = array(
'socid' => $socid);
3888 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerInvoiceRec', $parameters, $this, $action);
3890 $this->stats_facturerec = $hookmanager->resArray[
'stats_facturerec'];
3895 $this->error = $this->db->error();
3910 global $conf, $user, $hookmanager, $action;
3912 $sql =
"SELECT COUNT(DISTINCT f.fk_soc) as nb_suppliers, COUNT(DISTINCT f.rowid) as nb,";
3913 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(fd.qty) as qty";
3914 $sql .=
" FROM ".$this->db->prefix().
"facture_fourn_det as fd";
3915 $sql .=
", ".$this->db->prefix().
"facture_fourn as f";
3916 $sql .=
", ".$this->db->prefix().
"societe as s";
3917 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3918 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3920 $sql .=
" WHERE f.rowid = fd.fk_facture_fourn";
3921 $sql .=
" AND f.fk_soc = s.rowid";
3922 $sql .=
" AND f.entity IN (".getEntity(
'facture_fourn').
")";
3923 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
3924 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3925 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3929 $sql .=
" AND f.fk_soc = ".((int) $socid);
3932 $result = $this->db->query($sql);
3934 $obj = $this->db->fetch_object($result);
3935 $this->stats_facture_fournisseur[
'suppliers'] = $obj->nb_suppliers;
3936 $this->stats_facture_fournisseur[
'nb'] = $obj->nb;
3937 $this->stats_facture_fournisseur[
'rows'] = $obj->nb_rows;
3938 $this->stats_facture_fournisseur[
'qty'] = $obj->qty ? $obj->qty : 0;
3940 $parameters = array(
'socid' => $socid);
3941 $reshook = $hookmanager->executeHooks(
'loadStatsSupplierInvoice', $parameters, $this, $action);
3943 $this->stats_facture_fournisseur = $hookmanager->resArray[
'stats_facture_fournisseur'];
3948 $this->error = $this->db->error();
3967 $resql = $this->db->query($sql);
3969 $num = $this->db->num_rows($resql);
3972 $arr = $this->db->fetch_array($resql);
3973 if (is_array($arr)) {
3974 $keyfortab = (string) $arr[1];
3976 $keyfortab = substr($keyfortab, -2);
3979 if ($mode ==
'byunit') {
3980 $tab[$keyfortab] = (empty($tab[$keyfortab]) ? 0 : $tab[$keyfortab]) + $arr[0];
3981 } elseif ($mode ==
'bynumber') {
3982 $tab[$keyfortab] = (empty($tab[$keyfortab]) ? 0 : $tab[$keyfortab]) + $arr[2];
3983 } elseif ($mode ==
'byamount') {
3984 $tab[$keyfortab] = (empty($tab[$keyfortab]) ? 0 : $tab[$keyfortab]) + $arr[2];
3993 $this->error = $this->db->error().
' sql='.$sql;
4000 } elseif ($year == -1) {
4009 for ($j = 0; $j < 12; $j++) {
4011 $idx = ucfirst(
dol_trunc(
dol_print_date(
dol_mktime(12, 0, 0, $month, 1, 1970),
"%b"), 1,
'right',
'UTF-8', 1));
4014 $result[$j] = array($idx, isset($tab[$year.$month]) ? $tab[$year.$month] : 0);
4017 $month =
"0".($month - 1);
4019 $month = substr($month, 1);
4027 return array_reverse($result);
4042 public function get_nb_vente($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4048 $sql =
"SELECT sum(d.qty) as qty, date_format(f.datef, '%Y%m')";
4049 if ($mode ==
'bynumber') {
4050 $sql .=
", count(DISTINCT f.rowid)";
4052 $sql .=
", sum(d.total_ht) as total_ht";
4053 $sql .=
" FROM ".$this->db->prefix().
"facturedet as d, ".$this->db->prefix().
"facture as f, ".$this->db->prefix().
"societe as s";
4054 if ($filteronproducttype >= 0) {
4055 $sql .=
", ".$this->db->prefix().
"product as p";
4057 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4058 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4060 $sql .=
" WHERE f.rowid = d.fk_facture";
4061 if ($this->
id > 0) {
4062 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4064 $sql .=
" AND d.fk_product > 0";
4066 if ($filteronproducttype >= 0) {
4067 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4069 $sql .=
" AND f.fk_soc = s.rowid";
4070 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4071 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4072 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4075 $sql .=
" AND f.fk_soc = $socid";
4077 $sql .= $morefilter;
4078 $sql .=
" GROUP BY date_format(f.datef,'%Y%m')";
4079 $sql .=
" ORDER BY date_format(f.datef,'%Y%m') DESC";
4081 return $this->
_get_stats($sql, $mode, $year);
4096 public function get_nb_achat($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4102 $sql =
"SELECT sum(d.qty) as qty, date_format(f.datef, '%Y%m')";
4103 if ($mode ==
'bynumber') {
4104 $sql .=
", count(DISTINCT f.rowid)";
4106 $sql .=
", sum(d.total_ht) as total_ht";
4107 $sql .=
" FROM ".$this->db->prefix().
"facture_fourn_det as d, ".$this->db->prefix().
"facture_fourn as f, ".$this->db->prefix().
"societe as s";
4108 if ($filteronproducttype >= 0) {
4109 $sql .=
", ".$this->db->prefix().
"product as p";
4111 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4112 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4114 $sql .=
" WHERE f.rowid = d.fk_facture_fourn";
4115 if ($this->
id > 0) {
4116 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4118 $sql .=
" AND d.fk_product > 0";
4120 if ($filteronproducttype >= 0) {
4121 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4123 $sql .=
" AND f.fk_soc = s.rowid";
4124 $sql .=
" AND f.entity IN (".getEntity(
'facture_fourn').
")";
4125 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4126 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4129 $sql .=
" AND f.fk_soc = $socid";
4131 $sql .= $morefilter;
4132 $sql .=
" GROUP BY date_format(f.datef,'%Y%m')";
4133 $sql .=
" ORDER BY date_format(f.datef,'%Y%m') DESC";
4135 return $this->
_get_stats($sql, $mode, $year);
4149 public function get_nb_propal($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4152 global $conf, $user;
4154 $sql =
"SELECT sum(d.qty) as qty, date_format(p.datep, '%Y%m')";
4155 if ($mode ==
'bynumber') {
4156 $sql .=
", count(DISTINCT p.rowid)";
4158 $sql .=
", sum(d.total_ht) as total_ht";
4159 $sql .=
" FROM ".$this->db->prefix().
"propaldet as d, ".$this->db->prefix().
"propal as p, ".$this->db->prefix().
"societe as s";
4160 if ($filteronproducttype >= 0) {
4161 $sql .=
", ".$this->db->prefix().
"product as prod";
4163 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4164 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4166 $sql .=
" WHERE p.rowid = d.fk_propal";
4167 if ($this->
id > 0) {
4168 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4170 $sql .=
" AND d.fk_product > 0";
4172 if ($filteronproducttype >= 0) {
4173 $sql .=
" AND prod.rowid = d.fk_product AND prod.fk_product_type = ".((int) $filteronproducttype);
4175 $sql .=
" AND p.fk_soc = s.rowid";
4176 $sql .=
" AND p.entity IN (".getEntity(
'propal').
")";
4177 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4178 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4181 $sql .=
" AND p.fk_soc = ".((int) $socid);
4183 $sql .= $morefilter;
4184 $sql .=
" GROUP BY date_format(p.datep,'%Y%m')";
4185 $sql .=
" ORDER BY date_format(p.datep,'%Y%m') DESC";
4187 return $this->
_get_stats($sql, $mode, $year);
4207 $sql =
"SELECT sum(d.qty) as qty, date_format(p.date_valid, '%Y%m')";
4208 if ($mode ==
'bynumber') {
4209 $sql .=
", count(DISTINCT p.rowid)";
4211 $sql .=
", sum(d.total_ht) as total_ht";
4212 $sql .=
" FROM ".$this->db->prefix().
"supplier_proposaldet as d, ".$this->db->prefix().
"supplier_proposal as p, ".$this->db->prefix().
"societe as s";
4213 if ($filteronproducttype >= 0) {
4214 $sql .=
", ".$this->db->prefix().
"product as prod";
4216 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4217 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4219 $sql .=
" WHERE p.rowid = d.fk_supplier_proposal";
4220 if ($this->
id > 0) {
4221 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4223 $sql .=
" AND d.fk_product > 0";
4225 if ($filteronproducttype >= 0) {
4226 $sql .=
" AND prod.rowid = d.fk_product AND prod.fk_product_type = ".((int) $filteronproducttype);
4228 $sql .=
" AND p.fk_soc = s.rowid";
4229 $sql .=
" AND p.entity IN (".getEntity(
'supplier_proposal').
")";
4230 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4231 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4234 $sql .=
" AND p.fk_soc = ".((int) $socid);
4236 $sql .= $morefilter;
4237 $sql .=
" GROUP BY date_format(p.date_valid,'%Y%m')";
4238 $sql .=
" ORDER BY date_format(p.date_valid,'%Y%m') DESC";
4240 return $this->
_get_stats($sql, $mode, $year);
4254 public function get_nb_order($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4257 global $conf, $user;
4259 $sql =
"SELECT sum(d.qty) as qty, date_format(c.date_commande, '%Y%m')";
4260 if ($mode ==
'bynumber') {
4261 $sql .=
", count(DISTINCT c.rowid)";
4263 $sql .=
", sum(d.total_ht) as total_ht";
4264 $sql .=
" FROM ".$this->db->prefix().
"commandedet as d, ".$this->db->prefix().
"commande as c, ".$this->db->prefix().
"societe as s";
4265 if ($filteronproducttype >= 0) {
4266 $sql .=
", ".$this->db->prefix().
"product as p";
4268 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4269 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4271 $sql .=
" WHERE c.rowid = d.fk_commande";
4272 if ($this->
id > 0) {
4273 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4275 $sql .=
" AND d.fk_product > 0";
4277 if ($filteronproducttype >= 0) {
4278 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4280 $sql .=
" AND c.fk_soc = s.rowid";
4281 $sql .=
" AND c.entity IN (".getEntity(
'commande').
")";
4282 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4283 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4286 $sql .=
" AND c.fk_soc = ".((int) $socid);
4288 $sql .= $morefilter;
4289 $sql .=
" GROUP BY date_format(c.date_commande,'%Y%m')";
4290 $sql .=
" ORDER BY date_format(c.date_commande,'%Y%m') DESC";
4292 return $this->
_get_stats($sql, $mode, $year);
4309 global $conf, $user;
4311 $sql =
"SELECT sum(d.qty) as qty, date_format(c.date_commande, '%Y%m')";
4312 if ($mode ==
'bynumber') {
4313 $sql .=
", count(DISTINCT c.rowid)";
4315 $sql .=
", sum(d.total_ht) as total_ht";
4316 $sql .=
" FROM ".$this->db->prefix().
"commande_fournisseurdet as d, ".$this->db->prefix().
"commande_fournisseur as c, ".$this->db->prefix().
"societe as s";
4317 if ($filteronproducttype >= 0) {
4318 $sql .=
", ".$this->db->prefix().
"product as p";
4320 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4321 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4323 $sql .=
" WHERE c.rowid = d.fk_commande";
4324 if ($this->
id > 0) {
4325 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4327 $sql .=
" AND d.fk_product > 0";
4329 if ($filteronproducttype >= 0) {
4330 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4332 $sql .=
" AND c.fk_soc = s.rowid";
4333 $sql .=
" AND c.entity IN (".getEntity(
'supplier_order').
")";
4334 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4335 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4338 $sql .=
" AND c.fk_soc = ".((int) $socid);
4340 $sql .= $morefilter;
4341 $sql .=
" GROUP BY date_format(c.date_commande,'%Y%m')";
4342 $sql .=
" ORDER BY date_format(c.date_commande,'%Y%m') DESC";
4344 return $this->
_get_stats($sql, $mode, $year);
4358 public function get_nb_contract($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4361 global $conf, $user;
4363 $sql =
"SELECT sum(d.qty) as qty, date_format(c.date_contrat, '%Y%m')";
4364 if ($mode ==
'bynumber') {
4365 $sql .=
", count(DISTINCT c.rowid)";
4367 $sql .=
", sum(d.total_ht) as total_ht";
4368 $sql .=
" FROM ".$this->db->prefix().
"contratdet as d, ".$this->db->prefix().
"contrat as c, ".$this->db->prefix().
"societe as s";
4369 if ($filteronproducttype >= 0) {
4370 $sql .=
", ".$this->db->prefix().
"product as p";
4372 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4373 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4375 $sql .=
" WHERE c.entity IN (".getEntity(
'contract').
")";
4376 $sql .=
" AND c.rowid = d.fk_contrat";
4378 if ($this->
id > 0) {
4379 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4381 $sql .=
" AND d.fk_product > 0";
4383 if ($filteronproducttype >= 0) {
4384 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4386 $sql .=
" AND c.fk_soc = s.rowid";
4388 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4389 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4392 $sql .=
" AND c.fk_soc = ".((int) $socid);
4394 $sql .= $morefilter;
4395 $sql .=
" GROUP BY date_format(c.date_contrat,'%Y%m')";
4396 $sql .=
" ORDER BY date_format(c.date_contrat,'%Y%m') DESC";
4398 return $this->
_get_stats($sql, $mode, $year);
4412 public function get_nb_mos($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4415 global $conf, $user;
4417 $sql =
"SELECT sum(d.qty), date_format(d.date_valid, '%Y%m')";
4418 if ($mode ==
'bynumber') {
4419 $sql .=
", count(DISTINCT d.rowid)";
4421 $sql .=
" FROM ".$this->db->prefix().
"mrp_mo as d LEFT JOIN ".$this->db->prefix().
"societe as s ON d.fk_soc = s.rowid";
4422 if ($filteronproducttype >= 0) {
4423 $sql .=
", ".$this->db->prefix().
"product as p";
4425 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4426 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4429 $sql .=
" WHERE d.entity IN (".getEntity(
'mo').
")";
4430 $sql .=
" AND d.status > 0";
4432 if ($this->
id > 0) {
4433 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4435 $sql .=
" AND d.fk_product > 0";
4437 if ($filteronproducttype >= 0) {
4438 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4441 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4442 $sql .=
" AND d.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4445 $sql .=
" AND d.fk_soc = ".((int) $socid);
4447 $sql .= $morefilter;
4448 $sql .=
" GROUP BY date_format(d.date_valid,'%Y%m')";
4449 $sql .=
" ORDER BY date_format(d.date_valid,'%Y%m') DESC";
4451 return $this->
_get_stats($sql, $mode, $year);
4471 if (!is_numeric($id_pere)) {
4474 if (!is_numeric($id_fils)) {
4477 if (!is_numeric($incdec)) {
4487 $sql =
"SELECT fk_product_pere from ".$this->db->prefix().
"product_association";
4488 $sql .=
" WHERE fk_product_pere = ".((int) $id_fils).
" AND fk_product_fils = ".((int) $id_pere);
4489 if (!$this->db->query($sql)) {
4494 $sql =
"SELECT MAX(rang) as max_rank FROM ".$this->db->prefix().
"product_association";
4495 $sql .=
" WHERE fk_product_pere = ".((int) $id_pere);
4496 $resql = $this->db->query($sql);
4498 $obj = $this->db->fetch_object($resql);
4499 $rank = $obj->max_rank + 1;
4501 $sql =
"INSERT INTO ".$this->db->prefix().
"product_association(fk_product_pere,fk_product_fils,qty,incdec,rang)";
4502 $sql .=
" VALUES (".((int) $id_pere).
", ".((int) $id_fils).
", ".
price2num($qty,
'MS').
", ".
price2num($incdec,
'MS').
", ".((int) $rank).
")";
4503 if (! $this->db->query($sql)) {
4509 $result = $this->
call_trigger(
'PRODUCT_SUBPRODUCT_ADD', $user);
4511 $this->error = $this->db->lasterror();
4512 dol_syslog(get_class($this).
'::addSubproduct error='.$this->error, LOG_ERR);
4544 if (!is_numeric($id_pere)) {
4547 if (!is_numeric($id_fils)) {
4550 if (!is_numeric($incdec)) {
4553 if (!is_numeric($qty)) {
4557 $sql =
'UPDATE '.$this->db->prefix().
'product_association SET ';
4558 $sql .=
'qty = '.price2num($qty,
'MS');
4559 $sql .=
',incdec = '.price2num($incdec,
'MS');
4560 $sql .=
' WHERE fk_product_pere = '.((int) $id_pere).
' AND fk_product_fils = '.((int) $id_fils);
4562 if (!$this->db->query($sql)) {
4568 $result = $this->
call_trigger(
'PRODUCT_SUBPRODUCT_UPDATE', $user);
4570 $this->error = $this->db->lasterror();
4571 dol_syslog(get_class($this).
'::updateSubproduct error='.$this->error, LOG_ERR);
4595 if (!is_numeric($fk_parent)) {
4598 if (!is_numeric($fk_child)) {
4602 $sql =
"DELETE FROM ".$this->db->prefix().
"product_association";
4603 $sql .=
" WHERE fk_product_pere = ".((int) $fk_parent);
4604 $sql .=
" AND fk_product_fils = ".((int) $fk_child);
4606 dol_syslog(get_class($this).
'::del_sousproduit', LOG_DEBUG);
4607 if (!$this->db->query($sql)) {
4613 $sqlrank =
"SELECT rowid, rang FROM ".$this->db->prefix().
"product_association";
4614 $sqlrank .=
" WHERE fk_product_pere = ".((int) $fk_parent);
4615 $sqlrank .=
" ORDER BY rang";
4616 $resqlrank = $this->db->query($sqlrank);
4619 while ($objrank = $this->db->fetch_object($resqlrank)) {
4621 $sql =
"UPDATE ".$this->db->prefix().
"product_association";
4622 $sql .=
" SET rang = ".((int) $cpt);
4623 $sql .=
" WHERE rowid = ".((int) $objrank->rowid);
4624 if (! $this->db->query($sql)) {
4633 $result = $this->
call_trigger(
'PRODUCT_SUBPRODUCT_DELETE', $user);
4635 $this->error = $this->db->lasterror();
4636 dol_syslog(get_class($this).
'::delSubproduct error='.$this->error, LOG_ERR);
4656 $sql =
"SELECT fk_product_pere, qty, incdec";
4657 $sql .=
" FROM ".$this->db->prefix().
"product_association";
4658 $sql .=
" WHERE fk_product_pere = ".((int) $fk_parent);
4659 $sql .=
" AND fk_product_fils = ".((int) $fk_child);
4661 $result = $this->db->query($sql);
4663 $num = $this->db->num_rows($result);
4666 $obj = $this->db->fetch_object($result);
4668 $this->is_sousproduit_qty = $obj->qty;
4669 $this->is_sousproduit_incdec = $obj->incdec;
4700 dol_syslog(get_class($this).
"::add_fournisseur id_fourn = ".$id_fourn.
" ref_fourn=".
$ref_fourn.
" quantity=".$quantity, LOG_DEBUG);
4707 $sql =
"SELECT rowid, fk_product";
4708 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price";
4709 $sql .=
" WHERE fk_soc = ".((int) $id_fourn);
4710 $sql .=
" AND ref_fourn = '".$this->db->escape(
$ref_fourn).
"'";
4711 $sql .=
" AND fk_product <> ".((int) $this->
id);
4712 $sql .=
" AND entity IN (".getEntity(
'productsupplierprice').
")";
4714 $resql = $this->db->query($sql);
4716 $obj = $this->db->fetch_object($resql);
4719 $this->product_id_already_linked = $obj->fk_product;
4722 $this->db->free($resql);
4726 $sql =
"SELECT rowid";
4727 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price";
4728 $sql .=
" WHERE fk_soc = ".((int) $id_fourn);
4730 $sql .=
" AND ref_fourn = '".$this->db->escape(
$ref_fourn).
"'";
4732 $sql .=
" AND (ref_fourn = '' OR ref_fourn IS NULL)";
4734 $sql .=
" AND quantity = ".((float) $quantity);
4735 $sql .=
" AND fk_product = ".((int) $this->
id);
4736 $sql .=
" AND entity IN (".getEntity(
'productsupplierprice').
")";
4738 $resql = $this->db->query($sql);
4740 $obj = $this->db->fetch_object($resql);
4744 $sql =
"INSERT INTO ".$this->db->prefix().
"product_fournisseur_price(";
4747 $sql .=
", fk_product";
4749 $sql .=
", ref_fourn";
4750 $sql .=
", quantity";
4751 $sql .=
", fk_user";
4753 $sql .=
") VALUES (";
4754 $sql .=
"'".$this->db->idate($now).
"'";
4755 $sql .=
", ".((int) $conf->entity);
4756 $sql .=
", ".((int) $this->
id);
4757 $sql .=
", ".((int) $id_fourn);
4758 $sql .=
", '".$this->db->escape(
$ref_fourn).
"'";
4759 $sql .=
", ".((float) $quantity);
4760 $sql .=
", ".((int) $user->id);
4764 if ($this->db->query($sql)) {
4765 $this->product_fourn_price_id = $this->db->last_insert_id($this->db->prefix().
"product_fournisseur_price");
4768 $this->error = $this->db->lasterror();
4773 $this->product_fourn_price_id = $obj->rowid;
4777 $this->error = $this->db->lasterror();
4796 $sql =
"SELECT DISTINCT p.fk_soc";
4797 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price as p";
4798 $sql .=
" WHERE p.fk_product = ".((int) $this->
id);
4799 $sql .=
" AND p.entity = ".((int) $conf->entity);
4801 $result = $this->db->query($sql);
4803 $num = $this->db->num_rows($result);
4806 $obj = $this->db->fetch_object($result);
4807 $list[$i] = $obj->fk_soc;
4825 global $conf, $user;
4832 $sql =
"INSERT INTO ".$this->db->prefix().
"product_price (";
4834 $sql .=
", fk_product";
4835 $sql .=
", date_price";
4836 $sql .=
", price_level";
4838 $sql .=
", price_ttc";
4839 $sql .=
", price_min";
4840 $sql .=
", price_min_ttc";
4841 $sql .=
", price_base_type";
4842 $sql .=
", price_label";
4843 $sql .=
", default_vat_code";
4845 $sql .=
", recuperableonly";
4846 $sql .=
", localtax1_tx";
4847 $sql .=
", localtax1_type";
4848 $sql .=
", localtax2_tx";
4849 $sql .=
", localtax2_type";
4850 $sql .=
", fk_user_author";
4852 $sql .=
", price_by_qty";
4853 $sql .=
", fk_price_expression";
4854 $sql .=
", fk_multicurrency";
4855 $sql .=
", multicurrency_code";
4856 $sql .=
", multicurrency_tx";
4857 $sql .=
", multicurrency_price";
4858 $sql .=
", multicurrency_price_ttc";
4863 $sql .=
", '".$this->db->idate($now).
"'";
4864 $sql .=
", price_level";
4866 $sql .=
", price_ttc";
4867 $sql .=
", price_min";
4868 $sql .=
", price_min_ttc";
4869 $sql .=
", price_base_type";
4870 $sql .=
", price_label";
4871 $sql .=
", default_vat_code";
4873 $sql .=
", recuperableonly";
4874 $sql .=
", localtax1_tx";
4875 $sql .=
", localtax1_type";
4876 $sql .=
", localtax2_tx";
4877 $sql .=
", localtax2_type";
4878 $sql .=
", ".$user->id;
4880 $sql .=
", price_by_qty";
4881 $sql .=
", fk_price_expression";
4882 $sql .=
", fk_multicurrency";
4883 $sql .=
", multicurrency_code";
4884 $sql .=
", multicurrency_tx";
4885 $sql .=
", multicurrency_price";
4886 $sql .=
", multicurrency_price_ttc";
4887 $sql .=
" FROM ".$this->db->prefix().
"product_price ps";
4888 $sql .=
" WHERE fk_product = ".((int) $fromId);
4889 $sql .=
" AND date_price IN (SELECT MAX(pd.date_price) FROM ".$this->db->prefix().
"product_price pd WHERE pd.fk_product = ".((int) $fromId).
" AND pd.price_level = ps.price_level)";
4890 $sql .=
" ORDER BY date_price DESC";
4893 $resql = $this->db->query($sql);
4895 $this->db->rollback();
4899 $this->db->commit();
4916 $sql =
'INSERT INTO '.$this->db->prefix().
'product_association (fk_product_pere, fk_product_fils, qty, incdec)';
4917 $sql .=
" SELECT ".$toId.
", fk_product_fils, qty, incdec FROM ".$this->db->prefix().
"product_association";
4918 $sql .=
" WHERE fk_product_pere = ".((int) $fromId);
4920 dol_syslog(get_class($this).
'::clone_association', LOG_DEBUG);
4921 if (!$this->db->query($sql)) {
4922 $this->db->rollback();
4926 $this->db->commit();
4959 $sql =
"INSERT ".$this->db->prefix().
"product_fournisseur_price (";
4960 $sql .=
" datec, fk_product, fk_soc, price, quantity, fk_user, tva_tx)";
4961 $sql .=
" SELECT '".$this->db->idate($now).
"', ".((int) $toId).
", fk_soc, price, quantity, fk_user, tva_tx";
4962 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price";
4963 $sql .=
" WHERE fk_product = ".((int) $fromId);
4965 dol_syslog(get_class($this).
'::clone_fournisseurs', LOG_DEBUG);
4966 $resql = $this->db->query($sql);
4968 $this->db->rollback();
4971 $this->db->commit();
4989 public function fetch_prod_arbo($prod, $compl_path =
'', $multiply = 1, $level = 1, $id_parent = 0, $ignore_stock_load = 0)
4992 global $conf, $langs;
4996 foreach ($prod as $id_product => $desc_pere) {
4997 if (is_array($desc_pere)) {
4998 $id = (!empty($desc_pere[0]) ? $desc_pere[0] :
'');
4999 $nb = (!empty($desc_pere[1]) ? $desc_pere[1] :
'');
5000 $type = (!empty($desc_pere[2]) ? $desc_pere[2] :
'');
5001 $label = (!empty($desc_pere[3]) ? $desc_pere[3] :
'');
5002 $incdec = (!empty($desc_pere[4]) ? $desc_pere[4] : 0);
5004 if ($multiply < 1) {
5009 if (is_null($tmpproduct)) {
5010 $tmpproduct =
new Product($this->db);
5012 $tmpproduct->fetch($id);
5014 if (empty($ignore_stock_load) && ($tmpproduct->isProduct() ||
getDolGlobalString(
'STOCK_SUPPORTS_SERVICES'))) {
5015 $tmpproduct->load_stock(
'nobatch,novirtual');
5018 $this->res[] = array(
5020 'id_parent' => $id_parent,
5021 'ref' => $tmpproduct->ref,
5023 'nb_total' => $nb * $multiply,
5024 'stock' => $tmpproduct->stock_reel,
5025 'stock_alert' => $tmpproduct->seuil_stock_alerte,
5027 'fullpath' => $compl_path.$label,
5029 'desiredstock' => $tmpproduct->desiredstock,
5031 'incdec' => $incdec,
5032 'entity' => $tmpproduct->entity
5036 if (isset($desc_pere[
'childs']) && is_array($desc_pere[
'childs'])) {
5038 $this->
fetch_prod_arbo($desc_pere[
'childs'], $compl_path.$desc_pere[3].
" -> ", $desc_pere[1] * $multiply, $level + 1, $id, $ignore_stock_load);
5056 $this->res = array();
5057 if (isset($this->sousprods) && is_array($this->sousprods)) {
5058 foreach ($this->sousprods as $prod_name => $desc_product) {
5059 if (is_array($desc_product)) {
5060 $this->
fetch_prod_arbo($desc_product,
"", $multiply, 1, $this->
id, $ignore_stock_load);
5079 $sql =
"SELECT COUNT(pa.rowid) as nb";
5080 $sql .=
" FROM ".$this->db->prefix().
"product_association as pa";
5082 $sql .=
" WHERE pa.fk_product_fils = ".((int) $this->
id).
" OR pa.fk_product_pere = ".((int) $this->
id);
5083 } elseif ($mode == -1) {
5084 $sql .=
" WHERE pa.fk_product_fils = ".((int) $this->
id);
5085 } elseif ($mode == 1) {
5086 $sql .=
" WHERE pa.fk_product_pere = ".((int) $this->
id);
5089 $resql = $this->db->query($sql);
5091 $obj = $this->db->fetch_object($resql);
5110 $sql =
"SELECT count(rowid) as nb FROM ".$this->db->prefix().
"product_attribute_combination WHERE fk_product_parent = ".((int) $this->
id);
5111 $sql .=
" AND entity IN (".getEntity(
'product').
")";
5113 $resql = $this->db->query($sql);
5115 $obj = $this->db->fetch_object($resql);
5133 if (isModEnabled(
'variants')) {
5134 $sql =
"SELECT rowid FROM ".$this->db->prefix().
"product_attribute_combination WHERE fk_product_child = ".((int) $this->
id).
" AND entity IN (".
getEntity(
'product').
")";
5136 $query = $this->db->query($sql);
5139 if (!$this->db->num_rows($query)) {
5160 $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";
5161 $sql .=
", p.tosell as status, p.tobuy as status_buy";
5162 $sql .=
" FROM ".$this->db->prefix().
"product_association as pa,";
5163 $sql .=
" ".$this->db->prefix().
"product as p";
5164 $sql .=
" WHERE p.rowid = pa.fk_product_pere";
5165 $sql .=
" AND pa.fk_product_fils = ".((int) $this->
id);
5167 $res = $this->db->query($sql);
5170 while ($record = $this->db->fetch_array($res)) {
5172 $prods[$record[
'id']][
'id'] = $record[
'rowid'];
5173 $prods[$record[
'id']][
'ref'] = $record[
'ref'];
5174 $prods[$record[
'id']][
'label'] = $record[
'label'];
5175 $prods[$record[
'id']][
'qty'] = $record[
'qty'];
5176 $prods[$record[
'id']][
'incdec'] = $record[
'incdec'];
5177 $prods[$record[
'id']][
'fk_product_type'] = $record[
'fk_product_type'];
5178 $prods[$record[
'id']][
'entity'] = $record[
'entity'];
5179 $prods[$record[
'id']][
'status'] = $record[
'status'];
5180 $prods[$record[
'id']][
'status_buy'] = $record[
'status_buy'];
5199 public function getChildsArbo($id, $firstlevelonly = 0, $level = 1, $parents = array())
5201 global $alreadyfound;
5207 $sql =
"SELECT p.rowid, p.ref, p.label as label, p.fk_product_type,";
5208 $sql .=
" pa.qty as qty, pa.fk_product_fils as id, pa.incdec,";
5209 $sql .=
" pa.rowid as fk_association, pa.rang";
5210 $sql .=
" FROM ".$this->db->prefix().
"product as p,";
5211 $sql .=
" ".$this->db->prefix().
"product_association as pa";
5212 $sql .=
" WHERE p.rowid = pa.fk_product_fils";
5213 $sql .=
" AND pa.fk_product_pere = ".((int) $id);
5214 $sql .=
" AND pa.fk_product_fils <> ".((int) $id);
5215 $sql .=
" ORDER BY pa.rang";
5217 dol_syslog(get_class($this).
'::getChildsArbo id='.$id.
' level='.$level.
' parents='.(is_array($parents) ? implode(
',', $parents) : $parents), LOG_DEBUG);
5220 $alreadyfound = array($id => 1);
5227 $res = $this->db->query($sql);
5230 while ($rec = $this->db->fetch_array($res)) {
5231 if (!empty($alreadyfound[$rec[
'rowid']])) {
5232 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);
5233 if (in_array($rec[
'id'], $parents)) {
5237 $alreadyfound[$rec[
'rowid']] = 1;
5238 $prods[$rec[
'rowid']] = array(
5241 2 => $rec[
'fk_product_type'],
5242 3 => $this->db->escape($rec[
'label']),
5243 4 => $rec[
'incdec'],
5245 6 => $rec[
'fk_association'],
5250 if (empty($firstlevelonly)) {
5251 $parents[] = $rec[
'rowid'];
5252 $listofchilds = $this->
getChildsArbo($rec[
'rowid'], 0, $level + 1, $parents);
5253 foreach ($listofchilds as $keyChild => $valueChild) {
5254 $prods[$rec[
'rowid']][
'childs'][$keyChild] = $valueChild;
5278 foreach ($this->
getChildsArbo($this->
id) as $keyChild => $valueChild) {
5279 $parent[$this->label][$keyChild] = $valueChild;
5281 foreach ($parent as $key => $value) {
5282 $this->sousprods[$key] = $value;
5294 global $conf, $langs, $user;
5296 $langs->loadLangs(array(
'products',
'other'));
5299 $nofetch = !empty($params[
'nofetch']);
5302 return [
'optimize' => $langs->trans(
"ShowProduct")];
5306 $permissiontoreadproduct = 0;
5307 if ($this->
type == self::TYPE_PRODUCT && $user->hasRight(
'product',
'read')) {
5308 $permissiontoreadproduct = 1;
5310 if ($this->
type == self::TYPE_SERVICE && $user->hasRight(
'service',
'read')) {
5311 $permissiontoreadproduct = 1;
5314 if (!empty($this->entity) && $permissiontoreadproduct) {
5315 $tmpphoto = $this->
show_photos(
'product', $conf->product->multidir_output[$this->entity], 1, 1, 0, 0, 0, 80, 0, 0, 0, 0, 1);
5316 if ($this->nbphoto > 0) {
5317 $datas[
'photo'] =
'<div class="photointooltip floatright">'.
"\n" . $tmpphoto .
'</div>';
5322 $datas[
'picto'] =
img_picto(
'',
'product').
' <u class="paddingrightonly">'.$langs->trans(
"Product").
'</u>';
5324 $datas[
'picto'] =
img_picto(
'',
'service').
' <u class="paddingrightonly">'.$langs->trans(
"Service").
'</u>';
5326 if (isset($this->
status) && isset($this->status_buy)) {
5327 $datas[
'status'] =
' '.$this->getLibStatut(5, 0) .
' '.$this->getLibStatut(5, 1);
5330 if (!empty($this->
ref)) {
5331 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'ProductRef').
':</b> '.$this->ref;
5333 if (!empty($this->label)) {
5334 $datas[
'label'] =
'<br><b>'.$langs->trans(
'ProductLabel').
':</b> '.$this->label;
5337 if ($permissiontoreadproduct) {
5342 if (isModEnabled(
'productbatch')) {
5343 $langs->load(
"productbatch");
5344 $datas[
'batchstatus'] =
"<br><b>".$langs->trans(
"ManageLotSerial").
'</b>: '.$this->
getLibStatut(0, 2);
5347 if (isModEnabled(
'barcode')) {
5348 $datas[
'barcode'] =
'<br><b>'.$langs->trans(
'BarCode').
':</b> '.$this->barcode;
5352 if ($this->weight) {
5353 $datas[
'weight'] =
"<br><b>".$langs->trans(
"Weight").
'</b>: '.$this->weight.
' '.
measuringUnitString(0,
"weight", $this->weight_units);
5356 if ($this->length) {
5357 $labelsize .= ($labelsize ?
" - " :
"").
"<b>".$langs->trans(
"Length").
'</b>: '.$this->length.
' '.
measuringUnitString(0,
'size', $this->length_units);
5360 $labelsize .= ($labelsize ?
" - " :
"").
"<b>".$langs->trans(
"Width").
'</b>: '.$this->width.
' '.
measuringUnitString(0,
'size', $this->width_units);
5362 if ($this->height) {
5363 $labelsize .= ($labelsize ?
" - " :
"").
"<b>".$langs->trans(
"Height").
'</b>: '.$this->height.
' '.
measuringUnitString(0,
'size', $this->height_units);
5366 $datas[
'size'] =
"<br>".$labelsize;
5369 $labelsurfacevolume =
"";
5370 if ($this->surface) {
5371 $labelsurfacevolume .= ($labelsurfacevolume ?
" - " :
"").
"<b>".$langs->trans(
"Surface").
'</b>: '.$this->surface.
' '.
measuringUnitString(0,
'surface', $this->surface_units);
5373 if ($this->volume) {
5374 $labelsurfacevolume .= ($labelsurfacevolume ?
" - " :
"").
"<b>".$langs->trans(
"Volume").
'</b>: '.$this->volume.
' '.
measuringUnitString(0,
'volume', $this->volume_units);
5376 if ($labelsurfacevolume) {
5377 $datas[
'surface'] =
"<br>" . $labelsurfacevolume;
5383 if ($this->duration_value > 1) {
5384 $dur = array(
"i" => $langs->trans(
"Minutes"),
"h" => $langs->trans(
"Hours"),
"d" => $langs->trans(
"Days"),
"w" => $langs->trans(
"Weeks"),
"m" => $langs->trans(
"Months"),
"y" => $langs->trans(
"Years"));
5385 } elseif ($this->duration_value > 0) {
5386 $dur = array(
"i" => $langs->trans(
"Minute"),
"h" => $langs->trans(
"Hour"),
"d" => $langs->trans(
"Day"),
"w" => $langs->trans(
"Week"),
"m" => $langs->trans(
"Month"),
"y" => $langs->trans(
"Year"));
5388 $datas[
'duration'] .= (!empty($this->duration_unit) && isset($dur[$this->duration_unit]) ?
" ".$langs->trans($dur[$this->duration_unit]) :
'');
5390 if (empty($user->socid)) {
5392 $datas[
'pmp'] =
"<br><b>".$langs->trans(
"PMPValue").
'</b>: '.
price($this->pmp, 0,
'', 1, -1, -1, $conf->currency);
5395 if (isModEnabled(
'accounting')) {
5396 if ($this->
status && isset($this->accountancy_code_sell)) {
5397 include_once DOL_DOCUMENT_ROOT.
'/core/lib/accounting.lib.php';
5398 $selllabel =
'<br>';
5399 $selllabel .=
'<br><b>'.$langs->trans(
'ProductAccountancySellCode').
':</b> '.
length_accountg($this->accountancy_code_sell);
5400 $selllabel .=
'<br><b>'.$langs->trans(
'ProductAccountancySellIntraCode').
':</b> '.
length_accountg($this->accountancy_code_sell_intra);
5401 $selllabel .=
'<br><b>'.$langs->trans(
'ProductAccountancySellExportCode').
':</b> '.
length_accountg($this->accountancy_code_sell_export);
5402 $datas[
'accountancysell'] = $selllabel;
5404 if ($this->status_buy && isset($this->accountancy_code_buy)) {
5405 include_once DOL_DOCUMENT_ROOT.
'/core/lib/accounting.lib.php';
5407 if (empty($this->
status)) {
5408 $buylabel .=
'<br>';
5410 $buylabel .=
'<br><b>'.$langs->trans(
'ProductAccountancyBuyCode').
':</b> '.
length_accountg($this->accountancy_code_buy);
5411 $buylabel .=
'<br><b>'.$langs->trans(
'ProductAccountancyBuyIntraCode').
':</b> '.
length_accountg($this->accountancy_code_buy_intra);
5412 $buylabel .=
'<br><b>'.$langs->trans(
'ProductAccountancyBuyExportCode').
':</b> '.
length_accountg($this->accountancy_code_buy_export);
5413 $datas[
'accountancybuy'] = $buylabel;
5418 if (isModEnabled(
'category') && !$nofetch) {
5419 require_once DOL_DOCUMENT_ROOT .
'/categories/class/categorie.class.php';
5420 $form =
new Form($this->db);
5421 $datas[
'categories'] =
'<br>' . $form->showCategories($this->
id, Categorie::TYPE_PRODUCT, 1);
5441 public function getNomUrl($withpicto = 0, $option =
'', $maxlength = 0, $save_lastsearch_value = -1, $notooltip = 0, $morecss =
'', $add_label = 0, $sep =
' - ')
5443 global $langs, $hookmanager;
5444 include_once DOL_DOCUMENT_ROOT.
'/core/lib/product.lib.php';
5448 $newref = $this->ref;
5450 $newref =
dol_trunc($newref, $maxlength,
'middle');
5454 'objecttype' => (isset($this->
type) ? ($this->
type == 1 ?
'service' :
'product') : $this->element),
5455 'option' => $option,
5458 $classfortooltip =
'classfortooltip';
5461 $classfortooltip =
'classforajaxtooltip';
5462 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
5469 if (empty($notooltip)) {
5471 $label = $langs->trans(
"ShowProduct");
5472 $linkclose .=
' alt="'.dol_escape_htmltag($label, 1, 1).
'"';
5474 $linkclose .= ($label ?
' title="'.dol_escape_htmltag($label, 1, 1).
'"' :
' title="tocomplete"');
5475 $linkclose .= $dataparams.
' class="nowraponall '.$classfortooltip.($morecss ?
' '.$morecss :
'').
'"';
5477 $linkclose =
' class="nowraponall'.($morecss ?
' '.$morecss :
'').
'"';
5480 if ($option ==
'supplier' || $option ==
'category') {
5481 $url = DOL_URL_ROOT.
'/product/price_suppliers.php?id='.$this->id;
5482 } elseif ($option ==
'stock') {
5483 $url = DOL_URL_ROOT.
'/product/stock/product.php?id='.$this->id;
5484 } elseif ($option ==
'composition') {
5485 $url = DOL_URL_ROOT.
'/product/composition/card.php?id='.$this->id;
5487 $url = DOL_URL_ROOT.
'/product/card.php?id='.$this->id;
5490 if ($option !==
'nolink') {
5492 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
5493 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
5494 $add_save_lastsearch_values = 1;
5496 if ($add_save_lastsearch_values) {
5497 $url .=
'&save_lastsearch_values=1';
5501 $linkstart =
'<a href="'.$url.
'"';
5502 $linkstart .= $linkclose.
'>';
5505 $result .= $linkstart;
5508 $result .= (
img_object(($notooltip ?
'' : $label),
'product',
'class="paddingright"', 0, 0, $notooltip ? 0 : 1));
5511 $result .= (
img_object(($notooltip ?
'' : $label),
'service',
'class="paddingright"', 0, 0, $notooltip ? 0 : 1));
5514 $result .=
'<span class="aaa">'.dol_escape_htmltag($newref).
'</span>';
5515 $result .= $linkend;
5516 if ($withpicto != 2) {
5517 $result .= (($add_label && $this->label) ? $sep.dol_trunc($this->label, ($add_label > 1 ? $add_label : 0)) :
'');
5521 $hookmanager->initHooks(array(
'productdao'));
5522 $parameters = array(
'id' => $this->
id,
'getnomurl' => &$result,
'label' => &$label);
5523 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
5525 $result = $hookmanager->resPrint;
5527 $result .= $hookmanager->resPrint;
5544 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
5546 global $conf, $user, $langs;
5548 $langs->load(
"products");
5549 $outputlangs->load(
"products");
5556 $modelpath =
"core/modules/product/doc/";
5558 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
5574 return $this->
LibStatut($this->status_buy, $mode, $type);
5576 return $this->
LibStatut($this->status_batch, $mode, $type);
5579 return $this->
LibStatut($this->status_buy, $mode, $type);
5595 global $conf, $langs;
5597 $labelStatus = $labelStatusShort =
'';
5599 $langs->load(
'products');
5600 if (isModEnabled(
'productbatch')) {
5601 $langs->load(
"productbatch");
5607 $label = ($status == 0 ? $langs->transnoentitiesnoconv(
'ProductStatusNotOnBatch') : ($status == 1 ? $langs->transnoentitiesnoconv(
'ProductStatusOnBatch') : $langs->transnoentitiesnoconv(
'ProductStatusOnSerial')));
5608 return dolGetStatus($label);
5610 $label = ($status == 0 ? $langs->transnoentitiesnoconv(
'ProductStatusNotOnBatchShort') : ($status == 1 ? $langs->transnoentitiesnoconv(
'ProductStatusOnBatchShort') : $langs->transnoentitiesnoconv(
'ProductStatusOnSerialShort')));
5611 return dolGetStatus($label);
5615 return dolGetStatus($langs->transnoentitiesnoconv(
'ProductStatusNotOnBatch'),
'',
'', empty($status) ?
'status5' :
'status4', 3,
'dot');
5621 return dolGetStatus($langs->transnoentitiesnoconv(
'Unknown'));
5625 $statuttrans = empty($status) ?
'status5' :
'status4';
5630 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusNotOnSellShort');
5631 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusNotOnSell');
5632 } elseif ($type == 1) {
5633 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusNotOnBuyShort');
5634 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusNotOnBuy');
5635 } elseif ($type == 2) {
5636 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusNotOnBatch');
5637 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusNotOnBatchShort');
5639 } elseif ($status == 1) {
5642 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusOnSellShort');
5643 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusOnSell');
5644 } elseif ($type == 1) {
5645 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusOnBuyShort');
5646 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusOnBuy');
5647 } elseif ($type == 2) {
5648 $labelStatus = ($status == 1 ? $langs->transnoentitiesnoconv(
'ProductStatusOnBatch') : $langs->transnoentitiesnoconv(
'ProductStatusOnSerial'));
5649 $labelStatusShort = ($status == 1 ? $langs->transnoentitiesnoconv(
'ProductStatusOnBatchShort') : $langs->transnoentitiesnoconv(
'ProductStatusOnSerialShort'));
5651 } elseif ($type == 2 && $status == 2) {
5652 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusOnSerial');
5653 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusOnSerialShort');
5657 return dolGetStatus($langs->transnoentitiesnoconv(
'Unknown'),
'',
'',
'status0', 0);
5659 return dolGetStatus($labelStatus, $labelStatusShort,
'', $statuttrans, $mode);
5672 $langs->load(
'products');
5675 if (isset($this->finished) && $this->finished >= 0) {
5676 $sql =
"SELECT label, code FROM ".$this->db->prefix().
"c_product_nature where code = ".((int) $this->finished).
" AND active=1";
5677 $resql = $this->db->query($sql);
5679 $this->error = $this->db->error().
' sql='.$sql;
5680 dol_syslog(__METHOD__.
' Error '.$this->error, LOG_ERR);
5682 } elseif ($this->db->num_rows($resql) > 0 && $res = $this->db->fetch_array($resql)) {
5683 $label = $langs->trans($res[
'label']);
5685 $this->db->free($resql);
5709 public function correct_stock($user, $id_entrepot, $nbpiece, $movement, $label =
'', $price = 0, $inventorycode =
'', $origin_element =
'', $origin_id =
null, $disablestockchangeforsubproduct = 0, $extrafields =
null)
5715 include_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
5721 $nbpiece = abs($nbpiece);
5724 $op[0] =
"+".trim((
string) $nbpiece);
5725 $op[1] =
"-".trim((
string) $nbpiece);
5728 $movementstock->setOrigin($origin_element, $origin_id);
5729 $result = $movementstock->_create($user, $this->
id, $id_entrepot, $op[$movement], $movement, $price, $label, $inventorycode,
'',
'',
'',
'',
false, 0, $disablestockchangeforsubproduct);
5733 $array_options = $extrafields->getOptionalsFromPost(
'stock_mouvement');
5734 $movementstock->array_options = $array_options;
5735 $movementstock->insertExtraFields();
5737 $this->db->commit();
5740 $this->error = $movementstock->error;
5741 $this->errors = $movementstock->errors;
5743 $this->db->rollback();
5772 public function correct_stock_batch($user, $id_entrepot, $nbpiece, $movement, $label =
'', $price = 0, $dlc =
'', $dluo =
'', $lot =
'', $inventorycode =
'', $origin_element =
'', $origin_id =
null, $disablestockchangeforsubproduct = 0, $extrafields =
null, $force_update_batch =
false)
5778 include_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
5784 $nbpiece = abs($nbpiece);
5788 $op[0] =
"+".trim((
string) $nbpiece);
5789 $op[1] =
"-".trim((
string) $nbpiece);
5792 $movementstock->setOrigin($origin_element, $origin_id);
5793 $result = $movementstock->_create($user, $this->
id, $id_entrepot, $op[$movement], $movement, $price, $label, $inventorycode,
'', $dlc, $dluo, $lot,
false, 0, $disablestockchangeforsubproduct, 0, $force_update_batch);
5797 $array_options = $extrafields->getOptionalsFromPost(
'stock_mouvement');
5798 $movementstock->array_options = $array_options;
5799 $movementstock->insertExtraFields();
5801 $this->db->commit();
5804 $this->error = $movementstock->error;
5805 $this->errors = $movementstock->errors;
5807 $this->db->rollback();
5827 public function load_stock($option =
'', $includedraftpoforvirtual =
null, $dateofvirtualstock =
null)
5832 $this->stock_reel = 0;
5833 $this->stock_warehouse = array();
5834 $this->stock_theorique = 0;
5837 $warehouseStatus = array();
5838 if (preg_match(
'/warehouseclosed/', $option)) {
5841 if (preg_match(
'/warehouseopen/', $option)) {
5844 if (preg_match(
'/warehouseinternal/', $option)) {
5852 $sql =
"SELECT ps.rowid, ps.reel, ps.fk_entrepot";
5853 $sql .=
" FROM ".$this->db->prefix().
"product_stock as ps";
5854 $sql .=
", ".$this->db->prefix().
"entrepot as w";
5855 $sql .=
" WHERE w.entity IN (".getEntity(
'stock').
")";
5856 $sql .=
" AND w.rowid = ps.fk_entrepot";
5857 $sql .=
" AND ps.fk_product = ".((int) $this->
id);
5858 if (count($warehouseStatus)) {
5859 $sql .=
" AND w.statut IN (".$this->db->sanitize(implode(
',', $warehouseStatus)).
")";
5862 $sql .=
" ORDER BY ps.reel ".(getDolGlobalString(
'DO_NOT_TRY_TO_DEFRAGMENT_STOCKS_WAREHOUSE') ?
'DESC' :
'ASC');
5864 dol_syslog(get_class($this).
"::load_stock", LOG_DEBUG);
5865 $result = $this->db->query($sql);
5867 $num = $this->db->num_rows($result);
5871 $row = $this->db->fetch_object($result);
5872 $this->stock_warehouse[$row->fk_entrepot] =
new stdClass();
5873 $this->stock_warehouse[$row->fk_entrepot]->real = $row->reel;
5874 $this->stock_warehouse[$row->fk_entrepot]->id = $row->rowid;
5875 if ((!preg_match(
'/nobatch/', $option)) && $this->
hasbatch()) {
5876 $this->stock_warehouse[$row->fk_entrepot]->detail_batch =
Productbatch::findAll($this->db, $row->rowid, 1, $this->id);
5878 $this->stock_reel += $row->reel;
5882 $this->db->free($result);
5884 if (!preg_match(
'/novirtual/', $option)) {
5890 $this->error = $this->db->lasterror();
5909 global $conf, $hookmanager, $action;
5911 $stock_commande_client = 0;
5912 $stock_commande_fournisseur = 0;
5913 $stock_sending_client = 0;
5914 $stock_reception_fournisseur = 0;
5915 $stock_inproduction = 0;
5919 if (isModEnabled(
'order')) {
5924 $stock_commande_client = $this->stats_commande[
'qty'];
5926 if (isModEnabled(
"shipping")) {
5927 require_once DOL_DOCUMENT_ROOT.
'/expedition/class/expedition.class.php';
5928 $filterShipmentStatus =
'';
5938 $stock_sending_client = $this->stats_expedition[
'qty'];
5941 if (isModEnabled(
"supplier_order")) {
5942 $filterStatus =
getDolGlobalString(
'SUPPLIER_ORDER_STATUS_FOR_VIRTUAL_STOCK',
'3,4');
5943 if (isset($includedraftpoforvirtual)) {
5944 $filterStatus =
'0,1,2,'.$filterStatus;
5950 $stock_commande_fournisseur = $this->stats_commande_fournisseur[
'qty'];
5953 if ((isModEnabled(
"supplier_order") || isModEnabled(
"supplier_invoice")) && !isModEnabled(
'reception')) {
5955 $filterStatus =
'4';
5956 if (isset($includedraftpoforvirtual)) {
5957 $filterStatus =
'0,'.$filterStatus;
5963 $stock_reception_fournisseur = $this->stats_reception[
'qty'];
5966 if ((isModEnabled(
"supplier_order") || isModEnabled(
"supplier_invoice")) && isModEnabled(
"reception")) {
5968 $filterStatus =
'4';
5969 if (isset($includedraftpoforvirtual)) {
5970 $filterStatus =
'0,'.$filterStatus;
5976 $stock_reception_fournisseur = $this->stats_reception[
'qty'];
5979 if (isModEnabled(
'mrp')) {
5984 $stock_inproduction = $this->stats_mrptoproduce[
'qty'] - $this->stats_mrptoconsume[
'qty'];
5987 $this->stock_theorique = $this->stock_reel + $stock_inproduction;
5991 $this->stock_theorique -= ($stock_commande_client - $stock_sending_client);
5993 $this->stock_theorique += 0;
5995 $this->stock_theorique -= $stock_commande_client;
5999 $this->stock_theorique += ($stock_commande_fournisseur - $stock_reception_fournisseur);
6001 $this->stock_theorique += ($stock_commande_fournisseur - $stock_reception_fournisseur);
6003 $this->stock_theorique -= $stock_reception_fournisseur;
6005 $this->stock_theorique += ($stock_commande_fournisseur - $stock_reception_fournisseur);
6008 $parameters = array(
'id' => $this->
id,
'includedraftpoforvirtual' => $includedraftpoforvirtual);
6010 $reshook = $hookmanager->executeHooks(
'loadvirtualstock', $parameters, $this, $action);
6012 $this->stock_theorique = $hookmanager->resArray[
'stock_theorique'];
6013 } elseif ($reshook == 0 && isset($hookmanager->resArray[
'stock_stats_hook'])) {
6014 $this->stock_theorique += $hookmanager->resArray[
'stock_stats_hook'];
6018 if (!empty($this->stock_warehouse) &&
getDolGlobalString(
'STOCK_ALLOW_VIRTUAL_STOCK_PER_WAREHOUSE')) {
6019 foreach ($this->stock_warehouse as $warehouseid => $stockwarehouse) {
6020 if (isModEnabled(
'mrp')) {
6027 if ($this->fk_default_warehouse == $warehouseid) {
6028 $this->stock_warehouse[$warehouseid]->virtual = $this->stock_warehouse[$warehouseid]->real + $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] + $this->stats_commande_fournisseur[
'qty'] - ($this->stats_commande[
'qty'] + $this->stats_mrptoconsume[
'qty']);
6030 $this->stock_warehouse[$warehouseid]->virtual = $this->stock_warehouse[$warehouseid]->real + $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'];
6050 $sql =
"SELECT pb.batch, pb.eatby, pb.sellby, SUM(pb.qty) AS qty FROM ".$this->db->prefix().
"product_batch as pb, ".$this->db->prefix().
"product_stock as ps";
6051 $sql .=
" WHERE pb.fk_product_stock = ps.rowid AND ps.fk_product = ".((int) $this->
id).
" AND pb.batch = '".$this->db->escape($batch).
"'";
6052 $sql .=
" GROUP BY pb.batch, pb.eatby, pb.sellby";
6053 dol_syslog(get_class($this).
"::loadBatchInfo load first entry found for lot/serial = ".$batch, LOG_DEBUG);
6054 $resql = $this->db->query($sql);
6056 $num = $this->db->num_rows($resql);
6059 $obj = $this->db->fetch_object($resql);
6060 $result[] = array(
'batch' => $batch,
'eatby' => $this->db->jdate($obj->eatby),
'sellby' => $this->db->jdate($obj->sellby),
'qty' => $obj->qty);
6066 $this->db->rollback();
6084 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6090 $dir .=
'/'.get_exdir($this->
id, 2, 0, 0, $this,
'product').$this->id.
"/photos";
6092 $dir .=
'/'.get_exdir(0, 0, 0, 0, $this,
'product').dol_sanitizeFileName($this->
ref);
6097 $dir_osencoded = $dir;
6099 if (is_dir($dir_osencoded)) {
6100 $originImage = $dir.
'/'.$file[
'name'];
6111 if (is_numeric($result) && $result > 0) {
6128 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6129 include_once DOL_DOCUMENT_ROOT.
'/core/lib/images.lib.php';
6135 $dir .=
'/'.get_exdir($this->
id, 2, 0, 0, $this,
'product').$this->id.
"/photos/";
6137 $dir .=
'/'.get_exdir(0, 0, 0, 0, $this,
'product');
6143 if (file_exists($dir_osencoded)) {
6144 $handle = opendir($dir_osencoded);
6145 if (is_resource($handle)) {
6146 while (($file = readdir($handle)) !==
false) {
6148 $file = mb_convert_encoding($file,
'UTF-8',
'ISO-8859-1');
6170 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6171 include_once DOL_DOCUMENT_ROOT.
'/core/lib/images.lib.php';
6177 $handle = @opendir($dir_osencoded);
6178 if (is_resource($handle)) {
6179 while (($file = readdir($handle)) !==
false) {
6181 $file = mb_convert_encoding($file,
'UTF-8',
'ISO-8859-1');
6188 $photo_vignette =
'';
6190 if (preg_match(
'/('.$this->regeximgext.
')$/i', $photo, $regs)) {
6191 $photo_vignette = preg_replace(
'/'.$regs[0].
'/i',
'', $photo).
'_small'.$regs[0];
6194 $dirthumb = $dir.
'thumbs/';
6198 $obj[
'photo'] = $photo;
6199 if ($photo_vignette &&
dol_is_file($dirthumb.$photo_vignette)) {
6200 $obj[
'photo_vignette'] =
'thumbs/'.$photo_vignette;
6202 $obj[
'photo_vignette'] =
"";
6205 $tabobj[$nbphoto - 1] = $obj;
6208 if ($nbmax && $nbphoto >= $nbmax) {
6230 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6231 include_once DOL_DOCUMENT_ROOT.
'/core/lib/images.lib.php';
6233 $dir = dirname($file).
'/';
6234 $dirthumb = $dir.
'/thumbs/';
6235 $filename = preg_replace(
'/'.preg_quote($dir,
'/').
'/i',
'', $file);
6241 if (preg_match(
'/('.$this->regeximgext.
')$/i', $filename, $regs)) {
6242 $photo_vignette = preg_replace(
'/'.$regs[0].
'/i',
'', $filename).
'_small'.$regs[0];
6243 if (file_exists(
dol_osencode($dirthumb.$photo_vignette))) {
6247 $photo_vignette = preg_replace(
'/'.$regs[0].
'/i',
'', $filename).
'_mini'.$regs[0];
6248 if (file_exists(
dol_osencode($dirthumb.$photo_vignette))) {
6265 $infoImg = getimagesize($file_osencoded);
6266 $this->imgWidth = $infoImg[0];
6267 $this->imgHeight = $infoImg[1];
6277 global $hookmanager;
6279 $this->nb = array();
6281 $sql =
"SELECT count(p.rowid) as nb, fk_product_type";
6282 $sql .=
" FROM ".$this->db->prefix().
"product as p";
6283 $sql .=
' WHERE p.entity IN ('.getEntity($this->element, 1).
')';
6285 if (is_object($hookmanager)) {
6286 $parameters = array();
6287 $reshook = $hookmanager->executeHooks(
'printFieldListWhere', $parameters, $this);
6288 $sql .= $hookmanager->resPrint;
6290 $sql .=
' GROUP BY fk_product_type';
6292 $resql = $this->db->query($sql);
6294 while ($obj = $this->db->fetch_object($resql)) {
6295 if ($obj->fk_product_type == 1) {
6296 $this->nb[
"services"] = $obj->nb;
6298 $this->nb[
"products"] = $obj->nb;
6301 $this->db->free($resql);
6305 $this->error = $this->db->error();
6347 return ($this->mandatory_period == 1 ?
true :
false);
6357 return ($this->status_batch > 0 ?
true :
false);
6377 $dirsociete = array_merge(array(
'/core/modules/barcode/'), $conf->modules_parts[
'barcode']);
6378 foreach ($dirsociete as $dirroot) {
6386 '@phan-var-force ModeleNumRefBarCode $module';
6388 $result = $mod->getNextValue(
$object, $type);
6390 dol_syslog(get_class($this).
"::get_barcode barcode=".$result.
" module=".$var);
6407 $this->specimen = 1;
6409 $this->
ref =
'PRODUCT_SPEC';
6410 $this->label =
'PRODUCT SPECIMEN';
6411 $this->
description =
'This is description of this product specimen that was created the '.dol_print_date($now,
'dayhourlog').
'.';
6412 $this->specimen = 1;
6413 $this->country_id = 1;
6415 $this->status_buy = 1;
6417 $this->sell_or_eat_by_mandatory = 0;
6418 $this->note_private =
'This is a comment (private)';
6419 $this->note_public =
'This is a comment (public)';
6420 $this->date_creation = $now;
6421 $this->date_modification = $now;
6424 $this->weight_units = 3;
6427 $this->length_units = 1;
6429 $this->width_units = 0;
6430 $this->height =
null;
6431 $this->height_units =
null;
6433 $this->surface = 30;
6434 $this->surface_units = 0;
6435 $this->volume = 300;
6436 $this->volume_units = 0;
6438 $this->barcode = -1;
6453 if (!$this->fk_unit) {
6457 $langs->load(
'products');
6459 $label_type =
'label';
6460 if ($type ==
'short') {
6461 $label_type =
'short_label';
6464 $sql =
"SELECT ".$label_type.
", code from ".$this->db->prefix().
"c_units where rowid = ".((int) $this->fk_unit);
6466 $resql = $this->db->query($sql);
6468 $this->error = $this->db->error();
6469 dol_syslog(get_class($this).
"::getLabelOfUnit Error ".$this->error, LOG_ERR);
6471 } elseif ($this->db->num_rows($resql) > 0 && $res = $this->db->fetch_array($resql)) {
6472 $label = ($label_type ==
'short_label' ? $res[$label_type] :
'unit'.$res[
'code']);
6474 $this->db->free($resql);
6490 $maxpricesupplier = 0;
6493 include_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
6495 $product_fourn_list = $product_fourn->list_product_fournisseur_price($this->
id,
'',
'');
6497 if (is_array($product_fourn_list) && count($product_fourn_list) > 0) {
6498 foreach ($product_fourn_list as $productfourn) {
6499 if ($productfourn->fourn_unitprice > $maxpricesupplier) {
6500 $maxpricesupplier = $productfourn->fourn_unitprice;
6504 $maxpricesupplier *= $conf->global->PRODUCT_MINIMUM_RECOMMENDED_PRICE;
6508 return $maxpricesupplier;
6524 require_once DOL_DOCUMENT_ROOT.
'/categories/class/categorie.class.php';
6525 return parent::setCategoriesCommon($categories, Categorie::TYPE_PRODUCT);
6539 'product_customer_price',
6540 'product_customer_price_log'
6561 $sql =
"SELECT rowid, level, fk_level, var_percent, var_min_percent FROM ".$this->db->prefix().
"product_pricerules";
6562 $query = $this->db->query($sql);
6566 while ($result = $this->db->fetch_object($query)) {
6567 $rules[$result->level] = $result;
6576 for ($i = 1; $i <= $nbofproducts; $i++) {
6577 $price = $baseprice;
6578 $price_min = $baseprice;
6582 if ($i > 1 && isset($rules[$i]->var_percent) && $rules[$i]->var_percent) {
6583 $price = $prices[$rules[$i]->fk_level] * (1 + ($rules[$i]->var_percent / 100));
6586 $prices[$i] = $price;
6589 if (isset($rules[$i]->var_min_percent) && $rules[$i]->var_min_percent) {
6590 $price_min = $price * (1 - ($rules[$i]->var_min_percent / 100));
6594 $check_amount = (($price == $this->multiprices[$i]) && ($price_min == $this->multiprices_min[$i]));
6595 $check_type = ($baseprice == $this->multiprices_base_type[$i]);
6597 if ($check_amount && $check_type) {
6601 if ($this->
updatePrice($price, $price_type, $user, $price_vat, $price_min, $i, $npr, $psq,
true) < 0) {
6619 return $user->rights->produit;
6621 return $user->rights->service;
6633 $sql =
"SELECT p.rowid, p.ref, p.datec as date_creation, p.tms as date_modification,";
6634 $sql .=
" p.fk_user_author, p.fk_user_modif";
6635 $sql .=
" FROM ".$this->db->prefix().$this->table_element.
" as p";
6636 $sql .=
" WHERE p.rowid = ".((int) $id);
6638 $result = $this->db->query($sql);
6640 if ($this->db->num_rows($result)) {
6641 $obj = $this->db->fetch_object($result);
6643 $this->
id = $obj->rowid;
6644 $this->
ref = $obj->ref;
6646 $this->user_creation_id = $obj->fk_user_author;
6647 $this->user_modification_id = $obj->fk_user_modif;
6649 $this->date_creation = $this->db->jdate($obj->date_creation);
6650 $this->date_modification = $this->db->jdate($obj->date_modification);
6653 $this->db->free($result);
6669 if (empty($this->duration_value)) {
6670 $this->errors[] =
'ErrorDurationForServiceNotDefinedCantCalculateHourlyPrice';
6674 if ($this->duration_unit ==
'i') {
6675 $prodDurationHours = 1. / 60;
6677 if ($this->duration_unit ==
'h') {
6678 $prodDurationHours = 1.;
6680 if ($this->duration_unit ==
'd') {
6681 $prodDurationHours = 24.;
6683 if ($this->duration_unit ==
'w') {
6684 $prodDurationHours = 24. * 7;
6686 if ($this->duration_unit ==
'm') {
6687 $prodDurationHours = 24. * 30;
6689 if ($this->duration_unit ==
'y') {
6690 $prodDurationHours = 24. * 365;
6694 return $prodDurationHours;
6707 global $langs,$conf;
6709 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
6711 $return =
'<div class="box-flex-item box-flex-grow-zero">';
6712 $return .=
'<div class="info-box info-box-sm">';
6713 $return .=
'<div class="info-box-img">';
6716 $label .= $this->
show_photos(
'product', $conf->product->multidir_output[$this->entity], 1, 1, 0, 0, 0, 120, 160, 0, 0, 0,
'',
'photoref photokanban');
6726 $return .=
'</div>';
6727 $return .=
'<div class="info-box-content">';
6728 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this,
'getNomUrl') ? $this->
getNomUrl() : $this->ref).
'</span>';
6729 if ($selected >= 0) {
6730 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
6732 if (property_exists($this,
'label')) {
6733 $return .=
'<br><span class="info-box-label opacitymedium inline-block tdoverflowmax150 valignmiddle" title="'.dol_escape_htmltag($this->label).
'">'.
dol_escape_htmltag($this->label).
'</span>';
6735 if (property_exists($this,
'price') && property_exists($this,
'price_ttc')) {
6736 if ($this->price_base_type ==
'TTC') {
6737 $return .=
'<br><span class="info-box-status amount">'.price($this->price_ttc).
' '.$langs->trans(
"TTC").
'</span>';
6740 $return .=
'<br><span class="info-box-status amount">'.price($this->
price).
' '.$langs->trans(
"HT").
'</span>';
6745 if (property_exists($this,
'stock_reel') && $this->
isProduct()) {
6746 $return .=
'<br><div class="info-box-status opacitymedium inline-block valignmiddle">'.img_picto($langs->trans(
'PhysicalStock'),
'stock').
'</div><div class="inline-block valignmiddle paddingleft" title="'.$langs->trans(
'PhysicalStock').
'">'.$this->stock_reel.
'</div>';
6749 if (method_exists($this,
'getLibStatut')) {
6751 $return .=
'<br><div class="info-box-status inline-block valignmiddle">'.$this->getLibStatut(3, 1).
' '.$this->
getLibStatut(3, 0).
'</div>';
6753 $return .=
'<div class="info-box-status inline-block valignmiddle marginleftonly paddingleft">'.$this->getLibStatut(3, 1).
' '.$this->
getLibStatut(3, 0).
'</div>';
6756 $return .=
'</div>';
6757 $return .=
'</div>';
6758 $return .=
'</div>';
6769 public $picto =
'service';
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
length_accountg($account)
Return General accounting account with defined length (used for product and miscellaneous)
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Parent class of all other business classes (invoices, contracts, proposals, orders,...
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...
deleteEcmFiles($mode=0)
Delete related files of object in database.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
isObjectUsed($id=0, $entity=0)
Function to check if an object is used by others (by children).
deleteExtraFields()
Delete all extra fields values for the current object.
addThumbs($file)
Build thumb.
static commonReplaceThirdparty(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
show_photos($modulepart, $sdir, $size=0, $nbmax=0, $nbbyrow=5, $showfilename=0, $showaction=0, $maxHeight=120, $maxWidth=160, $nolink=0, $overwritetitle=0, $usesharelink=0, $cache='', $addphotorefcss='photoref')
Show photos of an object (nbmax maximum), into several columns.
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Class to manage Dolibarr database access.
const STATUS_OPEN_INTERNAL
Warehouse open and only operations for stock transfers/corrections allowed (not for customer shipping...
const STATUS_OPEN_ALL
Warehouse open and any operations are allowed (customer shipping, supplier dispatch,...
const STATUS_CLOSED
Warehouse closed, inactive.
const STATUS_CLOSED
Closed status -> parcel was received by customer / end of process prev status : validated or shipment...
const STATUS_VALIDATED
Validated status -> parcel is ready to be sent prev status : draft next status : closed or shipment_i...
const STATUS_DRAFT
Draft status.
Class to manage stock movements.
Class to parse product price expressions.
Class ProductCombination Used to represent the relation between a product and one of its variants.
File of class to manage predefined price products or services by customer.
Class to manage predefined suppliers products.
Class to manage products or services.
static replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
get_nb_achat($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter='')
Return nb of units or supplier invoices in which product is included.
getSellPrice($thirdparty_seller, $thirdparty_buyer, $pqp=0)
Return price of sell of a product for a seller/buyer/product.
__construct($db)
Constructor.
$price_by_qty
Price by quantity arrays.
is_sousproduit($fk_parent, $fk_child)
Check if it is a sub-product into a kit.
const SELL_OR_EAT_BY_MANDATORY_ID_NONE
Const sell or eat by mandatory id.
isStockManaged()
Return if object need to have its stock managed.
$duration
Service expiration label (value + unit)
setPriceExpression($expression_id)
Sets the supplier price expression.
getArrayForPriceCompare($level=0)
used to check if price have really change to avoid log pollution
get_arbo_each_prod($multiply=1, $ignore_stock_load=0)
Build the tree of subproducts and return it.
check_barcode($valuetotest, $typefortest)
Check barcode.
list_suppliers()
Return list of suppliers providing the product or service.
load_stats_mo($socid=0)
Charge tableau des stats OF pour le produit/service.
isVariant()
Return if loaded product is a variant.
updatePrice($newprice, $newpricebase, $user, $newvat=null, $newminprice=0, $level=0, $newnpr=0, $newpbq=0, $ignore_autogen=0, $localtaxes_array=array(), $newdefaultvatcode='', $price_label='', $notrigger=0)
Modify customer price of a product/Service for a given level.
hasVariants()
Return if a product has variants or not.
delMultiLangs($langtodelete, $user)
Delete a language for this product.
getLabelOfUnit($type='long')
Returns the text label from units dictionary.
load_stats_proposal_supplier($socid=0)
Charge tableau des stats propale pour le produit/service.
getLibFinished()
Retour label of nature of product.
add_sousproduit($id_pere, $id_fils, $qty, $incdec=1, $notrigger=0)
Link a product/service to a parent product/service.
add_fournisseur($user, $id_fourn, $ref_fourn, $quantity)
Add a supplier price for the product.
hasFatherOrChild($mode=0)
Count all parent and children products for current product (first level only)
load_stats_facturerec($socid=0)
Charge tableau des stats facture recurrentes pour le produit/service.
$product_id_already_linked
Product ID already linked to a reference supplier.
get_nb_propalsupplier($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter='')
Return nb of units in proposals in which product is included.
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_ordersupplier($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter='')
Return nb of units in orders in which product is included.
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.
clone_associations($fromId, $toId)
Clone links between products.
create($user, $notrigger=0)
Insert product into database.
load_stats_contrat($socid=0)
Charge tableau des stats contrat pour le produit/service.
isService()
Return if object is a product.
getRights()
Returns the rights used for this class.
loadBatchInfo($batch)
Load existing information about a serial.
$pmp
Average price value for product entry into stock (PMP)
load_stock($option='', $includedraftpoforvirtual=null, $dateofvirtualstock=null)
Load information about stock of a product into ->stock_reel, ->stock_warehouse[] (including stock_war...
getProductDurationHours()
Return the duration of a service in hours (for a service based on duration fields)
$default_vat_code
Default VAT code for product (link to code into llx_c_tva but without foreign keys)
$duration_unit
Service expiration unit.
get_buyprice($prodfournprice, $qty, $product_id=0, $fourn_ref='', $fk_soc=0)
Read price used by a provider.
clone_fournisseurs($fromId, $toId)
Recopie les fournisseurs et prix fournisseurs d'un produit/service sur un autre.
const TYPE_PRODUCT
Regular product.
$stock_warehouse
Contains detail of stock of product into each warehouse.
add_photo($sdir, $file)
Move an uploaded file described into $file array into target directory $sdir.
log_price_delete($user, $rowid)
Delete a price line.
info($id)
Load information for tab info.
correct_stock($user, $id_entrepot, $nbpiece, $movement, $label='', $price=0, $inventorycode='', $origin_element='', $origin_id=null, $disablestockchangeforsubproduct=0, $extrafields=null)
Adjust stock in a warehouse for product.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Create a document onto disk according to template module.
static getSellOrEatByMandatoryList()
Get sell or eat by mandatory list.
$multiprices
Arrays for multiprices.
$localtax1_tx
Other local taxes.
getChildsArbo($id, $firstlevelonly=0, $level=1, $parents=array())
Return children of product $id.
load_virtual_stock($includedraftpoforvirtual=null, $dateofvirtualstock=null)
Load value ->stock_theorique of a product.
load_stats_propale($socid=0)
Charge tableau des stats propale pour le produit/service.
get_barcode($object, $type='')
Get a barcode from the module to generate barcode values.
setAccountancyCode($type, $value)
Sets an accountancy code for a product.
load_stats_facture($socid=0)
Charge tableau des stats facture pour le produit/service.
$remise_percent
Default discount percent.
setCategories($categories)
Sets object to supplied categories.
load_stats_reception($socid=0, $filtrestatut='', $forVirtualStock=0, $dateofvirtualstock=null)
Charge tableau des stats réception fournisseur pour le produit/service.
get_nb_propal($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter='')
Return nb of units in proposals in which product is included.
update($id, $user, $notrigger=0, $action='update', $updatetype=false)
Update a record into database.
setMultiLangs($user)
Update or add a translation for a product.
correct_stock_batch($user, $id_entrepot, $nbpiece, $movement, $label='', $price=0, $dlc='', $dluo='', $lot='', $inventorycode='', $origin_element='', $origin_id=null, $disablestockchangeforsubproduct=0, $extrafields=null, $force_update_batch=false)
Adjust stock in a warehouse for product with batch number.
$tva_npr
int French VAT NPR is used (0 or 1)
$tva_tx
Default VAT rate of product.
load_stats_bom($socid=0)
Charge tableau des stats OF pour le produit/service.
hasbatch()
Return if object has a sell-by date or eat-by date.
$weight
Metric of products.
del_sousproduit($fk_parent, $fk_child, $notrigger=0)
Remove a link between a subproduct and a parent product/service.
fetch($id=0, $ref='', $ref_ext='', $barcode='', $ignore_expression=0, $ignore_price_load=0, $ignore_lang_load=0)
Load a product in memory from database.
update_sousproduit($id_pere, $id_fils, $qty, $incdec=1, $notrigger=0)
Modify composed product.
load_stats_commande($socid=0, $filtrestatut='', $forVirtualStock=0)
Charge tableau des stats commande client pour le produit/service.
delete_photo($file)
Delete a photo and its thumbs.
fetch_prod_arbo($prod, $compl_path='', $multiply=1, $level=1, $id_parent=0, $ignore_stock_load=0)
Function recursive, used only by get_arbo_each_prod(), to build tree of subproducts into ->res Define...
getKanbanView($option='', $arraydata=null)
Return clicable link of object (with eventually picto)
getLibStatut($mode=0, $type=0)
Return label of status of object.
load_stats_sending($socid=0, $filtrestatut='', $forVirtualStock=0, $filterShipmentStatus='')
Charge tableau des stats expedition client pour le produit/service.
clone_price($fromId, $toId)
Recopie les prix d'un produit/service sur un autre.
load_stats_inproduction($socid=0, $filtrestatut='', $forVirtualStock=0, $dateofvirtualstock=null, $warehouseid=0)
Charge tableau des stats production pour le produit/service.
$duration_value
Service expiration.
check()
Check that ref and label are ok.
initAsSpecimen()
Initialise an instance with random values.
liste_photos($dir, $nbmax=0)
Return an array with all photos of product found on disk.
loadStateBoard()
Load indicators this->nb for the dashboard.
getFather()
Return all parent products for current product (first level only)
getNomUrl($withpicto=0, $option='', $maxlength=0, $save_lastsearch_value=-1, $notooltip=0, $morecss='', $add_label=0, $sep=' - ')
Return clickable link of object (with eventually picto)
$product_fourn_id
Id du fournisseur.
getSellOrEatByMandatoryLabel()
Get sell or eat by mandatory label.
$desiredstock
Ask for replenishment when $desiredstock < $stock_reel.
verify()
Check properties of product are ok (like name, barcode, ...).
get_nb_order($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter='')
Return nb of units in orders in which product is included.
min_recommended_price()
Return minimum product recommended price.
_log_price($user, $level=0)
Insert a track that we changed a customer price.
_get_stats($sql, $mode, $year=0)
Return an array formatted for showing graphs.
$multilangs
Array for multilangs.
load_stats_commande_fournisseur($socid=0, $filtrestatut='', $forVirtualStock=0, $dateofvirtualstock=null)
Charge tableau des stats commande fournisseur pour le produit/service.
isMandatoryPeriod()
Return if object have a constraint on mandatory_period.
isProduct()
Return if object is a product.
generateMultiprices(User $user, $baseprice, $price_type, $price_vat, $npr, $psq)
Generates prices for a product based on product multiprice generation rules.
LibStatut($status, $mode=0, $type=0)
Return label of a given status.
const TYPE_SERVICE
Service.
is_photo_available($sdir)
Return if at least one photo is available.
get_image_size($file)
Load size of image file.
get_nb_vente($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter='')
Return nb of units or customers invoices in which product is included.
getTooltipContentArray($params)
getTooltipContentArray
Class to manage products or services.
Manage record for batch number management.
static findAll($dbs, $fk_product_stock, $with_qty=0, $fk_product=0)
Return all batch detail records for a given product and warehouse.
Class with list of lots and properties.
Class to manage Dolibarr users.
hasRight($module, $permlevel1, $permlevel2='')
Return if a user has a permission.
getCountry($searchkey, $withcode='', $dbtouse=null, $outputlangs=null, $entconv=1, $searchlabel='')
Return country label, code or id from an id, code or label.
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0, $indexdatabase=1, $nolog=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, $nolog=0)
Remove a file or several files with a mask.
dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disablevirusscan=0, $uploaderrorcode=0, $nohook=0, $varfiles='addedfile', $upload_dir='')
Check validity of a file upload from an GUI page, and move it to its final destination.
dol_is_file($pathoffile)
Return if path is a file.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dolGetFirstLineOfText($text, $nboflines=1, $charset='UTF-8')
Return first line of text.
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_string_nospecial($str, $newstr='_', $badcharstoreplace='', $badcharstoremove='', $keepspaces=0)
Clean a string from all punctuation characters to use it as a ref or login.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
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.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
if(!function_exists( 'dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
dol_clone($object, $native=0)
Create a clone of instance of object (new instance with same value for each properties) With native =...
get_default_npr(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that returns whether VAT must be recoverable collected VAT (e.g.: VAT NPR in France)
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
utf8_check($str)
Check if a string is in UTF8.
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) VAT...
get_localtax($vatrate, $local, $thirdparty_buyer=null, $thirdparty_seller=null, $vatnpr=0)
Return localtax rate for a particular vat, when selling a product with vat $vatrate,...
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
image_format_supported($file, $acceptsvg=0)
Return if a filename is file name of a supported image format.
measuringUnitString($unit, $measuring_style='', $scale='', $use_short_label=0, $outputlangs=null)
Return translation label of a unit key.
measuring_units_squared($unit)
Transform a given unit scale into the square of that unit, if known.
measuring_units_cubed($unit)
Transform a given unit scale into the cube of that unit, if known.
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type