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;
274 public $seuil_stock_alerte = 0;
297 public $fk_default_workstation;
319 public $status_buy = 0;
341 public $fk_default_bom;
348 public $product_fourn_price_id;
370 public $status_batch = 0;
377 public $sell_or_eat_by_mandatory = 0;
384 public $batch_mask =
'';
402 public $weight_units;
404 public $length_units;
408 public $height_units;
410 public $surface_units;
412 public $volume_units;
415 public $net_measure_units;
417 public $accountancy_code_sell;
418 public $accountancy_code_sell_intra;
419 public $accountancy_code_sell_export;
420 public $accountancy_code_buy;
421 public $accountancy_code_buy_intra;
422 public $accountancy_code_buy_export;
432 public $barcode_type;
437 public $barcode_type_code;
439 public $stats_propale = array();
440 public $stats_commande = array();
441 public $stats_contrat = array();
442 public $stats_facture = array();
443 public $stats_proposal_supplier = array();
444 public $stats_commande_fournisseur = array();
445 public $stats_expedition = array();
446 public $stats_reception = array();
447 public $stats_mo = array();
448 public $stats_bom = array();
449 public $stats_mrptoconsume = array();
450 public $stats_mrptoproduce = array();
451 public $stats_facturerec = array();
452 public $stats_facture_fournisseur = array();
461 public $date_creation;
466 public $date_modification;
482 public $fk_default_warehouse;
486 public $fk_price_expression;
491 public $fourn_price_base_type;
507 public $ref_supplier;
521 public $price_autogen = 0;
528 public $supplierprices;
535 public $sousprods = array();
548 public $is_object_used;
550 public $is_sousproduit_qty;
551 public $is_sousproduit_incdec;
553 public $mandatory_period;
584 public $fields = array(
585 'rowid' => array(
'type' =>
'integer',
'label' =>
'TechnicalID',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'index' => 1,
'position' => 1,
'comment' =>
'Id'),
586 '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'),
587 'entity' => array(
'type' =>
'integer',
'label' =>
'Entity',
'enabled' => 1,
'visible' => 0,
'default' =>
'1',
'notnull' => 1,
'index' => 1,
'position' => 5),
588 'label' => array(
'type' =>
'varchar(255)',
'label' =>
'Label',
'enabled' => 1,
'visible' => 1,
'notnull' => 1,
'showoncombobox' => 2,
'position' => 15,
'csslist' =>
'tdoverflowmax250'),
589 'barcode' => array(
'type' =>
'varchar(255)',
'label' =>
'Barcode',
'enabled' =>
'isModEnabled("barcode")',
'position' => 20,
'visible' => -1,
'showoncombobox' => 3,
'cssview' =>
'tdwordbreak',
'csslist' =>
'tdoverflowmax125'),
590 'fk_barcode_type' => array(
'type' =>
'integer',
'label' =>
'BarcodeType',
'enabled' => 1,
'position' => 21,
'notnull' => 0,
'visible' => -1,),
591 'note_public' => array(
'type' =>
'html',
'label' =>
'NotePublic',
'enabled' => 1,
'visible' => 0,
'position' => 61),
592 'note' => array(
'type' =>
'html',
'label' =>
'NotePrivate',
'enabled' => 1,
'visible' => 0,
'position' => 62),
593 'datec' => array(
'type' =>
'datetime',
'label' =>
'DateCreation',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 500),
594 'tms' => array(
'type' =>
'timestamp',
'label' =>
'DateModification',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 501),
596 'fk_user_author' => array(
'type' =>
'integer',
'label' =>
'UserAuthor',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 510,
'foreignkey' =>
'llx_user.rowid'),
597 'fk_user_modif' => array(
'type' =>
'integer',
'label' =>
'UserModif',
'enabled' => 1,
'visible' => -2,
'notnull' => -1,
'position' => 511),
599 'localtax1_tx' => array(
'type' =>
'double(6,3)',
'label' =>
'Localtax1tx',
'enabled' => 1,
'position' => 150,
'notnull' => 0,
'visible' => -1,),
600 'localtax1_type' => array(
'type' =>
'varchar(10)',
'label' =>
'Localtax1type',
'enabled' => 1,
'position' => 155,
'notnull' => 1,
'visible' => -1,),
601 'localtax2_tx' => array(
'type' =>
'double(6,3)',
'label' =>
'Localtax2tx',
'enabled' => 1,
'position' => 160,
'notnull' => 0,
'visible' => -1,),
602 'localtax2_type' => array(
'type' =>
'varchar(10)',
'label' =>
'Localtax2type',
'enabled' => 1,
'position' => 165,
'notnull' => 1,
'visible' => -1,),
603 'last_main_doc' => array(
'type' =>
'varchar(255)',
'label' =>
'LastMainDoc',
'enabled' => 1,
'visible' => -1,
'position' => 170),
604 'import_key' => array(
'type' =>
'varchar(14)',
'label' =>
'ImportId',
'enabled' => 1,
'visible' => -2,
'notnull' => -1,
'index' => 0,
'position' => 1000),
607 'mandatory_period' => array(
'type' =>
'integer',
'label' =>
'mandatoryperiod',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'default' =>
'0',
'index' => 1,
'position' => 1000),
628 $this->ismultientitymanaged = 1;
629 $this->isextrafieldmanaged = 1;
642 $this->
ref = trim($this->
ref);
670 public function create($user, $notrigger = 0)
672 global $conf, $langs;
678 $this->
ref = trim($this->
ref);
682 $this->label = trim($this->label);
683 $this->price_ttc = (float)
price2num($this->price_ttc);
685 $this->price_min_ttc = (float)
price2num($this->price_min_ttc);
686 $this->price_min = (float)
price2num($this->price_min);
687 $this->price_label = trim($this->price_label);
688 if (empty($this->tva_tx)) {
691 if (empty($this->tva_npr)) {
695 if (empty($this->localtax1_tx)) {
696 $this->localtax1_tx = 0;
698 if (empty($this->localtax2_tx)) {
699 $this->localtax2_tx = 0;
701 if (empty($this->localtax1_type)) {
702 $this->localtax1_type =
'0';
704 if (empty($this->localtax2_type)) {
705 $this->localtax2_type =
'0';
707 if (empty($this->
price)) {
710 if (empty($this->price_min)) {
711 $this->price_min = 0;
714 if (empty($this->price_by_qty)) {
715 $this->price_by_qty = 0;
718 if (empty($this->
status)) {
721 if (empty($this->status_buy)) {
722 $this->status_buy = 0;
731 if ($this->price_base_type ==
'TTC' && $this->price_ttc > 0) {
732 $price_ttc =
price2num($this->price_ttc,
'MU');
733 $price_ht =
price2num($this->price_ttc / (1 + ($this->tva_tx / 100)),
'MU');
737 if ($this->price_base_type !=
'TTC' && $this->
price > 0) {
739 $price_ttc =
price2num($this->
price * (1 + ($this->tva_tx / 100)),
'MU');
743 if (($this->price_min_ttc > 0) && ($this->price_base_type ==
'TTC')) {
744 $price_min_ttc =
price2num($this->price_min_ttc,
'MU');
745 $price_min_ht =
price2num($this->price_min_ttc / (1 + ($this->tva_tx / 100)),
'MU');
749 if (($this->price_min > 0) && ($this->price_base_type !=
'TTC')) {
750 $price_min_ht =
price2num($this->price_min,
'MU');
751 $price_min_ttc =
price2num($this->price_min * (1 + ($this->tva_tx / 100)),
'MU');
754 $this->accountancy_code_buy = trim($this->accountancy_code_buy);
755 $this->accountancy_code_buy_intra = trim($this->accountancy_code_buy_intra);
756 $this->accountancy_code_buy_export = trim($this->accountancy_code_buy_export);
757 $this->accountancy_code_sell = trim($this->accountancy_code_sell);
758 $this->accountancy_code_sell_intra = trim($this->accountancy_code_sell_intra);
759 $this->accountancy_code_sell_export = trim($this->accountancy_code_sell_export);
762 $this->barcode = trim($this->barcode);
763 $this->mandatory_period = empty($this->mandatory_period) ? 0 : $this->mandatory_period;
765 if (empty($this->label)) {
766 $this->error =
'ErrorMandatoryParametersNotProvided';
770 if (empty($this->
ref) || $this->
ref ==
'auto') {
773 if ($module !=
'mod_codeproduct_leopard') {
774 if (substr($module, 0, 16) ==
'mod_codeproduct_' && substr($module, -3) ==
'php') {
775 $module = substr($module, 0,
dol_strlen($module) - 4);
778 $modCodeProduct =
new $module();
779 '@phan-var-force ModeleProductCode $modCodeProduct';
780 if (!empty($modCodeProduct->code_auto)) {
781 $this->
ref = $modCodeProduct->getNextValue($this, $this->
type);
783 unset($modCodeProduct);
786 if (empty($this->
ref)) {
787 $this->error =
'ProductModuleNotSetupForAutoRef';
792 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);
796 if (empty($this->date_creation)) {
797 $this->date_creation = $now;
803 if ($this->barcode ==
'-1' || $this->barcode ==
'auto') {
804 $this->barcode = $this->
get_barcode($this, $this->barcode_type_code);
809 $result = $this->
verify();
812 $sql =
"SELECT count(*) as nb";
813 $sql .=
" FROM ".$this->db->prefix().
"product";
814 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
815 $sql .=
" AND ref = '".$this->db->escape($this->
ref).
"'";
817 $result = $this->db->query($sql);
819 $obj = $this->db->fetch_object($result);
822 $sql =
"INSERT INTO ".$this->db->prefix().
"product (";
827 $sql .=
", price_min";
828 $sql .=
", price_min_ttc";
830 $sql .=
", fk_user_author";
831 $sql .=
", fk_product_type";
833 $sql .=
", price_ttc";
834 $sql .=
", price_base_type";
835 $sql .=
", price_label";
839 $sql .=
", accountancy_code_buy";
840 $sql .=
", accountancy_code_buy_intra";
841 $sql .=
", accountancy_code_buy_export";
842 $sql .=
", accountancy_code_sell";
843 $sql .=
", accountancy_code_sell_intra";
844 $sql .=
", accountancy_code_sell_export";
847 $sql .=
", finished";
849 $sql .=
", sell_or_eat_by_mandatory";
850 $sql .=
", batch_mask";
852 $sql .=
", mandatory_period";
853 $sql .=
") VALUES (";
854 $sql .=
"'".$this->db->idate($this->date_creation).
"'";
855 $sql .=
", ".(!empty($this->entity) ? (int) $this->entity : (int) $conf->entity);
856 $sql .=
", '".$this->db->escape($this->
ref).
"'";
857 $sql .=
", ".(!empty($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
858 $sql .=
", ".price2num($price_min_ht);
859 $sql .=
", ".price2num($price_min_ttc);
860 $sql .=
", ".(!empty($this->label) ?
"'".$this->db->escape($this->label).
"'" :
"null");
861 $sql .=
", ".((int) $user->id);
862 $sql .=
", ".((int) $this->
type);
863 $sql .=
", ".price2num($price_ht,
'MT');
864 $sql .=
", ".price2num($price_ttc,
'MT');
865 $sql .=
", '".$this->db->escape($this->price_base_type).
"'";
866 $sql .=
", ".(!empty($this->price_label) ?
"'".$this->db->escape($this->price_label).
"'" :
"null");
867 $sql .=
", ".((int) $this->
status);
868 $sql .=
", ".((int) $this->status_buy);
870 $sql .=
", '".$this->db->escape($this->accountancy_code_buy).
"'";
871 $sql .=
", '".$this->db->escape($this->accountancy_code_buy_intra).
"'";
872 $sql .=
", '".$this->db->escape($this->accountancy_code_buy_export).
"'";
873 $sql .=
", '".$this->db->escape($this->accountancy_code_sell).
"'";
874 $sql .=
", '".$this->db->escape($this->accountancy_code_sell_intra).
"'";
875 $sql .=
", '".$this->db->escape($this->accountancy_code_sell_export).
"'";
877 $sql .=
", '".$this->db->escape($this->canvas).
"'";
878 $sql .=
", ".((!isset($this->finished) || $this->finished < 0 || $this->finished ==
'') ?
'NULL' : (int) $this->finished);
879 $sql .=
", ".((empty($this->status_batch) || $this->status_batch < 0) ?
'0' : ((int) $this->status_batch));
880 $sql .=
", ".((empty($this->sell_or_eat_by_mandatory) || $this->sell_or_eat_by_mandatory < 0) ? 0 : ((int) $this->sell_or_eat_by_mandatory));
881 $sql .=
", '".$this->db->escape($this->batch_mask).
"'";
882 $sql .=
", ".($this->fk_unit > 0 ? ((int) $this->fk_unit) :
'NULL');
883 $sql .=
", '".$this->db->escape($this->mandatory_period).
"'";
886 dol_syslog(get_class($this).
"::Create", LOG_DEBUG);
888 $result = $this->db->query($sql);
890 $id = $this->db->last_insert_id($this->db->prefix().
"product");
894 $this->
price = $price_ht;
895 $this->price_ttc = $price_ttc;
896 $this->price_min = $price_min_ht;
897 $this->price_min_ttc = $price_min_ttc;
901 if ($this->
update($id, $user,
true,
'add') <= 0) {
906 $this->error = $this->db->lasterror();
911 $this->db->query(
"DELETE FROM " . $this->db->prefix() .
"product_perentity WHERE fk_product = " .((int) $this->id) .
" AND entity = " . ((
int) $conf->entity));
913 $sql =
"INSERT INTO " . $this->db->prefix() .
"product_perentity (";
914 $sql .=
" fk_product";
916 $sql .=
", accountancy_code_buy";
917 $sql .=
", accountancy_code_buy_intra";
918 $sql .=
", accountancy_code_buy_export";
919 $sql .=
", accountancy_code_sell";
920 $sql .=
", accountancy_code_sell_intra";
921 $sql .=
", accountancy_code_sell_export";
922 $sql .=
") VALUES (";
924 $sql .=
", " . $conf->entity;
925 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy) .
"'";
926 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_intra) .
"'";
927 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_export) .
"'";
928 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell) .
"'";
929 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_intra) .
"'";
930 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_export) .
"'";
932 $result = $this->db->query($sql);
935 $this->error =
'ErrorFailedToInsertAccountancyForEntity';
940 $this->error =
'ErrorFailedToGetInsertedId';
944 $this->error = $this->db->lasterror();
948 $langs->load(
"products");
950 $this->error =
"ErrorProductAlreadyExists";
951 dol_syslog(get_class($this).
"::Create fails, ref ".$this->
ref.
" already exists");
955 $this->error = $this->db->lasterror();
958 if (!$error && !$notrigger) {
971 $this->db->rollback();
975 $this->db->rollback();
976 dol_syslog(get_class($this).
"::Create fails verify ".implode(
',', $this->errors), LOG_WARNING);
992 $this->errors = array();
995 $this->
ref = trim($this->
ref);
998 $this->errors[] =
'ErrorBadRef';
1002 $arrayofnonnegativevalue = array(
'weight' =>
'Weight',
'width' =>
'Width',
'height' =>
'Height',
'length' =>
'Length',
'surface' =>
'Surface',
'volume' =>
'Volume');
1003 foreach ($arrayofnonnegativevalue as $key => $value) {
1004 if (property_exists($this, $key) && !empty($this->$key) && ($this->$key < 0)) {
1005 $langs->loadLangs(array(
"main",
"other"));
1006 $this->error = $langs->trans(
"FieldCannotBeNegative", $langs->transnoentitiesnoconv($value));
1007 $this->errors[] = $this->error;
1012 $rescode = $this->
check_barcode($this->barcode, $this->barcode_type_code);
1014 if ($rescode == -1) {
1015 $this->errors[] =
'ErrorBadBarCodeSyntax';
1016 } elseif ($rescode == -2) {
1017 $this->errors[] =
'ErrorBarCodeRequired';
1018 } elseif ($rescode == -3) {
1020 $this->errors[] =
'ErrorBarCodeAlreadyUsed';
1047 $dirsociete = array_merge(array(
'/core/modules/barcode/'), $conf->modules_parts[
'barcode']);
1048 foreach ($dirsociete as $dirroot) {
1055 $mod =
new $module();
1056 '@phan-var-force ModeleNumRefBarCode $mod';
1058 dol_syslog(get_class($this).
"::check_barcode value=".$valuetotest.
" type=".$typefortest.
" module=".$module);
1059 $result = $mod->verif($this->db, $valuetotest, $this, 0, $typefortest);
1077 public function update($id, $user, $notrigger = 0, $action =
'update', $updatetype =
false)
1079 global $langs, $conf, $hookmanager;
1084 if (!$this->label) {
1085 $this->label =
'MISSING LABEL';
1090 $this->
ref = trim($this->
ref);
1094 $this->label = trim($this->label);
1096 $this->note_private = (isset($this->note_private) ? trim($this->note_private) :
null);
1097 $this->note_public = (isset($this->note_public) ? trim($this->note_public) :
null);
1098 $this->net_measure =
price2num($this->net_measure);
1099 $this->net_measure_units = (is_null($this->net_measure_units) ?
'' : trim((
string) $this->net_measure_units));
1100 $this->weight =
price2num($this->weight);
1101 $this->weight_units = (is_null($this->weight_units) ?
'' : trim((
string) $this->weight_units));
1102 $this->length =
price2num($this->length);
1103 $this->length_units = (is_null($this->length_units) ?
'' : trim((
string) $this->length_units));
1105 $this->width_units = (is_null($this->width_units) ?
'' : trim((
string) $this->width_units));
1106 $this->height =
price2num($this->height);
1107 $this->height_units = (is_null($this->height_units) ?
'' : trim((
string) $this->height_units));
1108 $this->surface =
price2num($this->surface);
1109 $this->surface_units = (is_null($this->surface_units) ?
'' : trim((
string) $this->surface_units));
1110 $this->volume =
price2num($this->volume);
1111 $this->volume_units = (is_null($this->volume_units) ?
'' : trim((
string) $this->volume_units));
1114 if (is_numeric($this->length_units)) {
1115 $this->width_units = $this->length_units;
1117 if (is_numeric($this->length_units)) {
1118 $this->height_units = $this->length_units;
1122 if (empty($this->surface) && !empty($this->length) && !empty($this->width) && $this->length_units == $this->width_units) {
1123 $this->surface = (float) $this->length * (
float) $this->width;
1126 if (empty($this->volume) && !empty($this->surface) && !empty($this->height) && $this->length_units == $this->height_units) {
1127 $this->volume = $this->surface * (float) $this->height;
1131 if (empty($this->tva_tx)) {
1134 if (empty($this->tva_npr)) {
1137 if (empty($this->localtax1_tx)) {
1138 $this->localtax1_tx = 0;
1140 if (empty($this->localtax2_tx)) {
1141 $this->localtax2_tx = 0;
1143 if (empty($this->localtax1_type)) {
1144 $this->localtax1_type =
'0';
1146 if (empty($this->localtax2_type)) {
1147 $this->localtax2_type =
'0';
1149 if (empty($this->
status)) {
1152 if (empty($this->status_buy)) {
1153 $this->status_buy = 0;
1156 if (empty($this->country_id)) {
1157 $this->country_id = 0;
1160 if (empty($this->state_id)) {
1161 $this->state_id = 0;
1165 $this->barcode = (empty($this->barcode) ?
'' : trim($this->barcode));
1167 $this->accountancy_code_buy = trim($this->accountancy_code_buy);
1168 $this->accountancy_code_buy_intra = (!empty($this->accountancy_code_buy_intra) ? trim($this->accountancy_code_buy_intra) :
'');
1169 $this->accountancy_code_buy_export = trim($this->accountancy_code_buy_export);
1170 $this->accountancy_code_sell = trim($this->accountancy_code_sell);
1171 $this->accountancy_code_sell_intra = trim($this->accountancy_code_sell_intra);
1172 $this->accountancy_code_sell_export = trim($this->accountancy_code_sell_export);
1179 if ($action !=
'add') {
1180 $result = $this->
verify();
1188 if (is_null($this->oldcopy) || (is_object($this->oldcopy) && $this->oldcopy->isEmpty())) {
1193 if ($this->
hasbatch() && !$this->oldcopy->hasbatch()) {
1195 $valueforundefinedlot =
'000000';
1200 dol_syslog(
"Flag batch of product id=".$this->
id.
" is set to ON, so we will create missing records into product_batch");
1203 foreach ($this->stock_warehouse as $idW => $ObjW) {
1205 foreach ($ObjW->detail_batch as $detail) {
1206 if ($detail->batch == $valueforundefinedlot || $detail->batch ==
'Undefined') {
1208 $sqlclean =
"DELETE FROM ".$this->db->prefix().
"product_batch WHERE batch in('Undefined', '".$this->db->escape($valueforundefinedlot).
"') AND fk_product_stock = ".((int) $ObjW->id);
1209 $result = $this->db->query($sqlclean);
1217 $qty_batch += $detail->qty;
1221 if ($ObjW->real != $qty_batch) {
1223 $ObjBatch->batch = $valueforundefinedlot;
1224 $ObjBatch->qty = ($ObjW->real - $qty_batch);
1225 $ObjBatch->fk_product_stock = $ObjW->id;
1227 if ($ObjBatch->create($user, 1) < 0) {
1229 $this->errors = $ObjBatch->errors;
1234 if ($ObjLot->fetch(0, $this->id, $valueforundefinedlot) == 0) {
1235 $ObjLot->fk_product = $this->id;
1236 $ObjLot->entity = $this->entity;
1237 $ObjLot->fk_user_creat = $user->id;
1238 $ObjLot->batch = $valueforundefinedlot;
1239 if ($ObjLot->create($user,
true) < 0) {
1241 $this->errors = $ObjLot->errors;
1250 if ($this->barcode == -1) {
1251 $this->barcode = $this->
get_barcode($this, $this->barcode_type_code);
1254 $sql =
"UPDATE ".$this->db->prefix().
"product";
1255 $sql .=
" SET label = '".$this->db->escape($this->label).
"'";
1258 $sql .=
", fk_product_type = ".((int) $this->
type);
1261 $sql .=
", ref = '".$this->db->escape($this->
ref).
"'";
1262 $sql .=
", ref_ext = ".(!empty($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
1263 $sql .=
", default_vat_code = ".($this->default_vat_code ?
"'".$this->db->escape($this->default_vat_code).
"'" :
"null");
1264 $sql .=
", tva_tx = ".((float) $this->tva_tx);
1265 $sql .=
", recuperableonly = ".((int) $this->tva_npr);
1266 $sql .=
", localtax1_tx = ".((float) $this->localtax1_tx);
1267 $sql .=
", localtax2_tx = ".((float) $this->localtax2_tx);
1268 $sql .=
", localtax1_type = ".($this->localtax1_type !=
'' ?
"'".$this->db->escape($this->localtax1_type).
"'" :
"'0'");
1269 $sql .=
", localtax2_type = ".($this->localtax2_type !=
'' ?
"'".$this->db->escape($this->localtax2_type).
"'" :
"'0'");
1271 $sql .=
", barcode = ".(empty($this->barcode) ?
"null" :
"'".$this->db->escape($this->barcode).
"'");
1272 $sql .=
", fk_barcode_type = ".(empty($this->barcode_type) ?
"null" : $this->db->escape($this->barcode_type));
1274 $sql .=
", tosell = ".(int) $this->
status;
1275 $sql .=
", tobuy = ".(int) $this->status_buy;
1276 $sql .=
", tobatch = ".((empty($this->status_batch) || $this->status_batch < 0) ?
'0' : (int) $this->status_batch);
1277 $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);
1278 $sql .=
", batch_mask = '".$this->db->escape($this->batch_mask).
"'";
1280 $sql .=
", finished = ".((!isset($this->finished) || $this->finished < 0 || $this->finished ===
'') ?
"null" : (int) $this->finished);
1281 $sql .=
", fk_default_bom = ".((!isset($this->fk_default_bom) || $this->fk_default_bom < 0 || $this->fk_default_bom ==
'') ?
"null" : (int) $this->fk_default_bom);
1282 $sql .=
", net_measure = ".($this->net_measure !=
'' ?
"'".$this->db->escape($this->net_measure).
"'" :
'null');
1283 $sql .=
", net_measure_units = ".($this->net_measure_units !=
'' ?
"'".$this->db->escape($this->net_measure_units).
"'" :
'null');
1284 $sql .=
", weight = ".($this->weight !=
'' ?
"'".$this->db->escape($this->weight).
"'" :
'null');
1285 $sql .=
", weight_units = ".($this->weight_units !=
'' ?
"'".$this->db->escape($this->weight_units).
"'" :
'null');
1286 $sql .=
", length = ".($this->length !=
'' ?
"'".$this->db->escape($this->length).
"'" :
'null');
1287 $sql .=
", length_units = ".($this->length_units !=
'' ?
"'".$this->db->escape($this->length_units).
"'" :
'null');
1288 $sql .=
", width= ".($this->width !=
'' ?
"'".$this->db->escape($this->width).
"'" :
'null');
1289 $sql .=
", width_units = ".($this->width_units !=
'' ?
"'".$this->db->escape($this->width_units).
"'" :
'null');
1290 $sql .=
", height = ".($this->height !=
'' ?
"'".$this->db->escape($this->height).
"'" :
'null');
1291 $sql .=
", height_units = ".($this->height_units !=
'' ?
"'".$this->db->escape($this->height_units).
"'" :
'null');
1292 $sql .=
", surface = ".($this->surface !=
'' ?
"'".$this->db->escape($this->surface).
"'" :
'null');
1293 $sql .=
", surface_units = ".($this->surface_units !=
'' ?
"'".$this->db->escape($this->surface_units).
"'" :
'null');
1294 $sql .=
", volume = ".($this->volume !=
'' ?
"'".$this->db->escape($this->volume).
"'" :
'null');
1295 $sql .=
", volume_units = ".($this->volume_units !=
'' ?
"'".$this->db->escape($this->volume_units).
"'" :
'null');
1296 $sql .=
", fk_default_warehouse = ".($this->fk_default_warehouse > 0 ? ((int) $this->fk_default_warehouse) :
'null');
1297 $sql .=
", fk_default_workstation = ".($this->fk_default_workstation > 0 ? ((int) $this->fk_default_workstation) :
'null');
1298 $sql .=
", seuil_stock_alerte = ".((isset($this->seuil_stock_alerte) && is_numeric($this->seuil_stock_alerte)) ? (
float) $this->seuil_stock_alerte :
'null');
1299 $sql .=
", description = '".$this->db->escape($this->
description).
"'";
1300 $sql .=
", url = ".($this->url ?
"'".$this->db->escape($this->url).
"'" :
'null');
1301 $sql .=
", customcode = '".$this->db->escape($this->customcode).
"'";
1302 $sql .=
", fk_country = ".($this->country_id > 0 ? (int) $this->country_id :
'null');
1303 $sql .=
", fk_state = ".($this->state_id > 0 ? (int) $this->state_id :
'null');
1304 $sql .=
", lifetime = ".($this->lifetime > 0 ? (int) $this->lifetime :
'null');
1305 $sql .=
", qc_frequency = ".($this->qc_frequency > 0 ? (int) $this->qc_frequency :
'null');
1306 $sql .=
", note = ".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
'null');
1307 $sql .=
", note_public = ".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
'null');
1308 $sql .=
", duration = '".$this->db->escape($this->duration_value.$this->duration_unit).
"'";
1310 $sql .=
", accountancy_code_buy = '" . $this->db->escape($this->accountancy_code_buy) .
"'";
1311 $sql .=
", accountancy_code_buy_intra = '" . $this->db->escape($this->accountancy_code_buy_intra) .
"'";
1312 $sql .=
", accountancy_code_buy_export = '" . $this->db->escape($this->accountancy_code_buy_export) .
"'";
1313 $sql .=
", accountancy_code_sell= '" . $this->db->escape($this->accountancy_code_sell) .
"'";
1314 $sql .=
", accountancy_code_sell_intra= '" . $this->db->escape($this->accountancy_code_sell_intra) .
"'";
1315 $sql .=
", accountancy_code_sell_export= '" . $this->db->escape($this->accountancy_code_sell_export) .
"'";
1317 $sql .=
", desiredstock = ".((isset($this->desiredstock) && is_numeric($this->desiredstock)) ? (
float) $this->desiredstock :
"null");
1318 $sql .=
", cost_price = ".($this->cost_price !=
'' ? ((float) $this->cost_price) :
'null');
1319 $sql .=
", fk_unit= ".(!$this->fk_unit ?
'NULL' : (int) $this->fk_unit);
1320 $sql .=
", price_autogen = ".(!$this->price_autogen ? 0 : 1);
1321 $sql .=
", fk_price_expression = ".($this->fk_price_expression != 0 ? (int) $this->fk_price_expression :
'NULL');
1322 $sql .=
", fk_user_modif = ".($user->id > 0 ? (int) $user->id :
'NULL');
1323 $sql .=
", mandatory_period = ".((int) $this->mandatory_period);
1325 $sql .=
" WHERE rowid = ".((int) $id);
1327 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
1329 $resql = $this->db->query($sql);
1336 $this->db->rollback();
1345 $this->db->query(
"DELETE FROM " . $this->db->prefix() .
"product_perentity WHERE fk_product = " . ((
int) $this->id) .
" AND entity = " . ((
int) $conf->entity));
1347 $sql =
"INSERT INTO " . $this->db->prefix() .
"product_perentity (";
1348 $sql .=
" fk_product";
1350 $sql .=
", accountancy_code_buy";
1351 $sql .=
", accountancy_code_buy_intra";
1352 $sql .=
", accountancy_code_buy_export";
1353 $sql .=
", accountancy_code_sell";
1354 $sql .=
", accountancy_code_sell_intra";
1355 $sql .=
", accountancy_code_sell_export";
1356 $sql .=
") VALUES (";
1358 $sql .=
", " . $conf->entity;
1359 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy) .
"'";
1360 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_intra) .
"'";
1361 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_export) .
"'";
1362 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell) .
"'";
1363 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_intra) .
"'";
1364 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_export) .
"'";
1366 $result = $this->db->query($sql);
1369 $this->error =
'ErrorFailedToUpdateAccountancyForEntity';
1373 if (!$this->
hasbatch() && $this->oldcopy->hasbatch()) {
1375 $sql =
'SELECT pb.qty, ps.fk_entrepot, pb.batch FROM '.MAIN_DB_PREFIX.
'product_batch as pb';
1376 $sql .=
' INNER JOIN '.MAIN_DB_PREFIX.
'product_stock as ps ON (ps.rowid = pb.fk_product_stock)';
1377 $sql .=
' WHERE ps.fk_product = '.(int) $this->
id;
1379 $resql = $this->db->query($sql);
1383 while ($obj = $this->db->fetch_object($resql)) {
1385 $fk_entrepot = $obj->fk_entrepot;
1389 $batch = $obj->batch;
1392 $addOremove = $value > 0 ? 1 : 0;
1393 $label = $langs->trans(
'BatchStockMouvementAddInGlobal');
1394 $res = $this->
correct_stock_batch($user, $fk_entrepot, abs($value), $addOremove, $label, $price, $dlc, $dluo, $batch, $inventorycode,
'',
null, 0,
null,
true);
1397 $label = $langs->trans(
'BatchStockMouvementAddInGlobal');
1398 $res = $this->
correct_stock($user, $fk_entrepot, abs($value), (
int) empty($addOremove), $label, $price, $inventorycode,
'',
null, 0);
1417 if (!$error && !$notrigger) {
1419 $result = $this->
call_trigger(
'PRODUCT_MODIFY', $user);
1426 if (!$error && (is_object($this->oldcopy) && $this->oldcopy->ref !== $this->ref)) {
1428 if ($conf->product->dir_output) {
1431 if (file_exists($olddir)) {
1435 $res = @rename($olddir, $newdir);
1437 $langs->load(
"errors");
1438 $this->error = $langs->trans(
'ErrorFailToRenameDir', $olddir, $newdir);
1446 if (isModEnabled(
'variants')) {
1447 include_once DOL_DOCUMENT_ROOT.
'/variants/class/ProductCombination.class.php';
1451 foreach ($comb->fetchAllByFkProductParent($this->id) as $currcomb) {
1452 $currcomb->updateProperties($this, $user);
1456 $this->db->commit();
1459 $this->db->rollback();
1463 if ($this->db->errno() ==
'DB_ERROR_RECORD_ALREADY_EXISTS') {
1464 $langs->load(
"errors");
1465 if (empty($conf->barcode->enabled) || empty($this->barcode)) {
1466 $this->error = $langs->trans(
"Error").
" : ".$langs->trans(
"ErrorProductAlreadyExists", $this->
ref);
1468 $this->error = $langs->trans(
"Error").
" : ".$langs->trans(
"ErrorProductBarCodeAlreadyExists", $this->barcode);
1470 $this->errors[] = $this->error;
1471 $this->db->rollback();
1474 $this->error = $langs->trans(
"Error").
" : ".$this->db->error().
" - ".$sql;
1475 $this->errors[] = $this->error;
1476 $this->db->rollback();
1481 $this->db->rollback();
1482 dol_syslog(get_class($this).
"::Update fails verify ".implode(
',', $this->errors), LOG_WARNING);
1494 public function delete(
User $user, $notrigger = 0)
1496 global $conf, $langs;
1497 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1502 if (empty($this->
id)) {
1503 $this->error =
"Object must be fetched before calling delete";
1507 $this->error =
"ErrorForbidden";
1512 if (empty($objectisused)) {
1515 if (!$error && empty($notrigger)) {
1517 $result = $this->
call_trigger(
'PRODUCT_DELETE', $user);
1526 $sql =
"DELETE FROM ".$this->db->prefix().
'product_batch';
1527 $sql .=
" WHERE fk_product_stock IN (";
1528 $sql .=
"SELECT rowid FROM ".$this->db->prefix().
'product_stock';
1529 $sql .=
" WHERE fk_product = ".((int) $this->
id).
")";
1531 $result = $this->db->query($sql);
1534 $this->errors[] = $this->db->lasterror();
1540 $elements = array(
'product_fournisseur_price',
'product_price',
'product_lang',
'categorie_product',
'product_stock',
'product_customer_price',
'product_lot');
1541 foreach ($elements as $table) {
1543 $sql =
"DELETE FROM ".$this->db->prefix().$table;
1544 $sql .=
" WHERE fk_product = ".(int) $this->
id;
1546 $result = $this->db->query($sql);
1549 $this->errors[] = $this->db->lasterror();
1556 include_once DOL_DOCUMENT_ROOT.
'/variants/class/ProductCombination.class.php';
1557 include_once DOL_DOCUMENT_ROOT.
'/variants/class/ProductCombination2ValuePair.class.php';
1562 if ($prodcomb->deleteByFkProductParent($user, $this->id) < 0) {
1564 $this->errors[] =
'Error deleting combinations';
1568 if (!$error && ($prodcomb->fetchByFkProductChild($this->id) > 0) && ($prodcomb->delete($user) < 0)) {
1570 $this->errors[] =
'Error deleting child combination';
1576 $sql =
"DELETE FROM ".$this->db->prefix().
"product_association";
1577 $sql .=
" WHERE fk_product_pere = ".(int) $this->
id.
" OR fk_product_fils = ".(
int) $this->id;
1579 $result = $this->db->query($sql);
1582 $this->errors[] = $this->db->lasterror();
1591 dol_syslog(get_class($this).
"::delete error -4 ".$this->error, LOG_ERR);
1597 $sqlz =
"DELETE FROM ".$this->db->prefix().
"product";
1598 $sqlz .=
" WHERE rowid = ".(int) $this->
id;
1600 $resultz = $this->db->query($sqlz);
1603 $this->errors[] = $this->db->lasterror();
1619 if ($conf->product->dir_output) {
1620 $dir = $conf->product->dir_output.
"/".$ref;
1621 if (file_exists($dir)) {
1624 $this->errors[] =
'ErrorFailToDeleteDir';
1632 $this->db->commit();
1635 foreach ($this->errors as $errmsg) {
1636 dol_syslog(get_class($this).
"::delete ".$errmsg, LOG_ERR);
1637 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1639 $this->db->rollback();
1643 $this->error =
"ErrorRecordIsUsedCantDelete";
1657 $sellByLabel = $langs->trans(
'SellByDate');
1658 $eatByLabel = $langs->trans(
'EatByDate');
1660 self::SELL_OR_EAT_BY_MANDATORY_ID_NONE => $langs->trans(
'BatchSellOrEatByMandatoryNone'),
1661 self::SELL_OR_EAT_BY_MANDATORY_ID_SELL_BY => $sellByLabel,
1662 self::SELL_OR_EAT_BY_MANDATORY_ID_EAT_BY => $eatByLabel,
1663 self::SELL_OR_EAT_BY_MANDATORY_ID_SELL_AND_EAT => $langs->trans(
'BatchSellOrEatByMandatoryAll', $sellByLabel, $eatByLabel),
1674 $sellOrEatByMandatoryLabel =
'';
1677 if (isset($sellOrEatByMandatoryList[$this->sell_or_eat_by_mandatory])) {
1678 $sellOrEatByMandatoryLabel = $sellOrEatByMandatoryList[$this->sell_or_eat_by_mandatory];
1681 return $sellOrEatByMandatoryLabel;
1692 global $conf, $langs;
1694 $langs_available = $langs->get_available_languages(DOL_DOCUMENT_ROOT, 0, 2);
1695 $current_lang = $langs->getDefaultLang();
1697 foreach ($langs_available as $key => $value) {
1698 if ($key == $current_lang) {
1699 $sql =
"SELECT rowid";
1700 $sql .=
" FROM ".$this->db->prefix().
"product_lang";
1701 $sql .=
" WHERE fk_product = ".((int) $this->
id);
1702 $sql .=
" AND lang = '".$this->db->escape($key).
"'";
1704 $result = $this->db->query($sql);
1706 if ($this->db->num_rows($result)) {
1707 $sql2 =
"UPDATE ".$this->db->prefix().
"product_lang";
1709 $sql2 .=
" label='".$this->db->escape($this->label).
"',";
1710 $sql2 .=
" description='".$this->db->escape($this->
description).
"'";
1712 $sql2 .=
", note='".$this->db->escape($this->other).
"'";
1714 $sql2 .=
" WHERE fk_product = ".((int) $this->
id).
" AND lang = '".$this->db->escape($key).
"'";
1716 $sql2 =
"INSERT INTO ".$this->db->prefix().
"product_lang (fk_product, lang, label, description";
1721 $sql2 .=
" VALUES(".((int) $this->
id).
",'".$this->db->escape($key).
"','".$this->db->escape($this->label).
"',";
1722 $sql2 .=
" '".$this->db->escape($this->
description).
"'";
1724 $sql2 .=
", '".$this->db->escape($this->other).
"'";
1728 dol_syslog(get_class($this).
'::setMultiLangs key = current_lang = '.$key);
1729 if (!$this->db->query($sql2)) {
1730 $this->error = $this->db->lasterror();
1733 } elseif (isset($this->multilangs[$key])) {
1734 if (empty($this->multilangs[
"$key"][
"label"])) {
1735 $this->errors[] = $key .
' : ' . $langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv(
"Label"));
1739 $sql =
"SELECT rowid";
1740 $sql .=
" FROM ".$this->db->prefix().
"product_lang";
1741 $sql .=
" WHERE fk_product = ".((int) $this->
id);
1742 $sql .=
" AND lang = '".$this->db->escape($key).
"'";
1744 $result = $this->db->query($sql);
1746 if ($this->db->num_rows($result)) {
1747 $sql2 =
"UPDATE ".$this->db->prefix().
"product_lang";
1749 $sql2 .=
" label = '".$this->db->escape($this->multilangs[
"$key"][
"label"]).
"',";
1750 $sql2 .=
" description = '".$this->db->escape($this->multilangs[
"$key"][
"description"]).
"'";
1752 $sql2 .=
", note = '".$this->db->escape($this->multilangs[
"$key"][
"other"]).
"'";
1754 $sql2 .=
" WHERE fk_product = ".((int) $this->
id).
" AND lang = '".$this->db->escape($key).
"'";
1756 $sql2 =
"INSERT INTO ".$this->db->prefix().
"product_lang (fk_product, lang, label, description";
1761 $sql2 .=
" VALUES(".((int) $this->
id).
",'".$this->db->escape($key).
"','".$this->db->escape($this->multilangs[
"$key"][
"label"]).
"',";
1762 $sql2 .=
" '".$this->db->escape($this->multilangs[
"$key"][
"description"]).
"'";
1764 $sql2 .=
", '".$this->db->escape($this->multilangs[
"$key"][
"other"]).
"'";
1770 if ($this->multilangs[
"$key"][
"label"] || $this->multilangs[
"$key"][
"description"]) {
1771 if (!$this->db->query($sql2)) {
1772 $this->error = $this->db->lasterror();
1782 $result = $this->
call_trigger(
'PRODUCT_SET_MULTILANGS', $user);
1784 $this->error = $this->db->lasterror();
1802 $sql =
"DELETE FROM ".$this->db->prefix().
"product_lang";
1803 $sql .=
" WHERE fk_product = ".((int) $this->
id).
" AND lang = '".$this->db->escape($langtodelete).
"'";
1805 dol_syslog(get_class($this).
'::delMultiLangs', LOG_DEBUG);
1806 $result = $this->db->query($sql);
1809 $result = $this->
call_trigger(
'PRODUCT_DEL_MULTILANGS', $user);
1811 $this->error = $this->db->lasterror();
1812 dol_syslog(get_class($this).
'::delMultiLangs error='.$this->error, LOG_ERR);
1818 $this->error = $this->db->lasterror();
1819 dol_syslog(get_class($this).
'::delMultiLangs error='.$this->error, LOG_ERR);
1834 global $user, $langs, $conf;
1840 if ($type ==
'buy') {
1841 $field =
'accountancy_code_buy';
1842 } elseif ($type ==
'buy_intra') {
1843 $field =
'accountancy_code_buy_intra';
1844 } elseif ($type ==
'buy_export') {
1845 $field =
'accountancy_code_buy_export';
1846 } elseif ($type ==
'sell') {
1847 $field =
'accountancy_code_sell';
1848 } elseif ($type ==
'sell_intra') {
1849 $field =
'accountancy_code_sell_intra';
1850 } elseif ($type ==
'sell_export') {
1851 $field =
'accountancy_code_sell_export';
1856 $sql =
"UPDATE ".$this->db->prefix().$this->table_element.
" SET ";
1857 $sql .=
"$field = '".$this->db->escape($value).
"'";
1858 $sql .=
" WHERE rowid = ".((int) $this->
id);
1861 $resql = $this->db->query($sql);
1865 $result = $this->
call_trigger(
'PRODUCT_MODIFY', $user);
1872 $this->db->rollback();
1876 $this->$field = $value;
1878 $this->db->commit();
1881 $this->error = $this->db->lasterror();
1882 $this->db->rollback();
1896 $current_lang = $langs->getDefaultLang();
1898 $sql =
"SELECT lang, label, description, note as other";
1899 $sql .=
" FROM ".$this->db->prefix().
"product_lang";
1900 $sql .=
" WHERE fk_product = ".((int) $this->
id);
1902 $result = $this->db->query($sql);
1904 while ($obj = $this->db->fetch_object($result)) {
1906 if ($obj->lang == $current_lang) {
1907 $this->label = $obj->label;
1909 $this->other = $obj->other;
1911 $this->multilangs[(string) $obj->lang][
"label"] = $obj->label;
1912 $this->multilangs[(string) $obj->lang][
"description"] = $obj->description;
1913 $this->multilangs[(string) $obj->lang][
"other"] = $obj->other;
1917 $this->error =
"Error: ".$this->db->lasterror().
" - ".$sql;
1930 $testExit = array(
'multiprices',
'multiprices_ttc',
'multiprices_base_type',
'multiprices_min',
'multiprices_min_ttc',
'multiprices_tva_tx',
'multiprices_recuperableonly');
1932 foreach ($testExit as $field) {
1933 if (!isset($this->$field)) {
1936 $tmparray = $this->$field;
1937 if (!isset($tmparray[$level])) {
1943 'level' => $level ? $level : 1,
1944 'multiprices' => (float) $this->multiprices[$level],
1945 'multiprices_ttc' => (
float) $this->multiprices_ttc[$level],
1946 'multiprices_base_type' => $this->multiprices_base_type[$level],
1947 'multiprices_min' => (float) $this->multiprices_min[$level],
1948 'multiprices_min_ttc' => (
float) $this->multiprices_min_ttc[$level],
1949 'multiprices_tva_tx' => (float) $this->multiprices_tva_tx[$level],
1950 'multiprices_recuperableonly' => (
float) $this->multiprices_recuperableonly[$level],
1973 if (empty($this->price_by_qty)) {
1974 $this->price_by_qty = 0;
1978 $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,";
1979 $sql .=
" localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, price_min,price_min_ttc,price_by_qty,entity,fk_price_expression) ";
1980 $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).
",";
1981 $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');
1984 dol_syslog(get_class($this).
"::_log_price", LOG_DEBUG);
1985 $resql = $this->db->query($sql);
1987 $this->error = $this->db->lasterror();
2007 $sql =
"DELETE FROM ".$this->db->prefix().
"product_price_by_qty";
2008 $sql .=
" WHERE fk_product_price = ".((int) $rowid);
2009 $resql = $this->db->query($sql);
2011 $sql =
"DELETE FROM ".$this->db->prefix().
"product_price";
2012 $sql .=
" WHERE rowid=".((int) $rowid);
2013 $resql = $this->db->query($sql);
2017 $this->error = $this->db->lasterror();
2032 public function getSellPrice($thirdparty_seller, $thirdparty_buyer, $pqp = 0)
2034 global $conf, $hookmanager, $action;
2037 if (is_object($hookmanager)) {
2038 $parameters = array(
'thirdparty_seller' => $thirdparty_seller,
'thirdparty_buyer' => $thirdparty_buyer,
'pqp' => $pqp);
2040 $reshook = $hookmanager->executeHooks(
'getSellPrice', $parameters, $this, $action);
2042 return $hookmanager->resArray;
2053 $pu_ht = $this->price;
2054 $pu_ttc = $this->price_ttc;
2055 $price_min = $this->price_min;
2056 $price_base_type = $this->price_base_type;
2059 if (
getDolGlobalString(
'PRODUIT_MULTIPRICES') && !empty($thirdparty_buyer->price_level)) {
2060 $pu_ht = $this->multiprices[$thirdparty_buyer->price_level];
2061 $pu_ttc = $this->multiprices_ttc[$thirdparty_buyer->price_level];
2062 $price_min = $this->multiprices_min[$thirdparty_buyer->price_level];
2063 $price_base_type = $this->multiprices_base_type[$thirdparty_buyer->price_level];
2065 if (isset($this->multiprices_tva_tx[$thirdparty_buyer->price_level])) {
2066 $tva_tx = $this->multiprices_tva_tx[$thirdparty_buyer->price_level];
2068 if (isset($this->multiprices_recuperableonly[$thirdparty_buyer->price_level])) {
2069 $tva_npr = $this->multiprices_recuperableonly[$thirdparty_buyer->price_level];
2077 require_once DOL_DOCUMENT_ROOT.
'/product/class/productcustomerprice.class.php';
2081 $filter = array(
't.fk_product' => $this->
id,
't.fk_soc' => $thirdparty_buyer->id);
2083 $result = $prodcustprice->fetchAll(
'',
'', 0, 0, $filter);
2085 if (count($prodcustprice->lines) > 0) {
2086 $pu_ht =
price($prodcustprice->lines[0]->price);
2087 $price_min =
price($prodcustprice->lines[0]->price_min);
2088 $pu_ttc =
price($prodcustprice->lines[0]->price_ttc);
2089 $price_base_type = $prodcustprice->lines[0]->price_base_type;
2090 $tva_tx = $prodcustprice->lines[0]->tva_tx;
2091 if ($prodcustprice->lines[0]->default_vat_code && !preg_match(
'/\(.*\)/',
$tva_tx)) {
2092 $tva_tx .=
' ('.$prodcustprice->lines[0]->default_vat_code.
')';
2094 $tva_npr = $prodcustprice->lines[0]->recuperableonly;
2102 if ($this->prices_by_qty[0]) {
2105 foreach ($this->prices_by_qty_list[0] as $priceforthequantityarray) {
2106 if ($priceforthequantityarray[
'rowid'] != $pqp) {
2110 if ($priceforthequantityarray[
'price_base_type'] ==
'HT') {
2111 $pu_ht = $priceforthequantityarray[
'unitprice'];
2113 $pu_ttc = $priceforthequantityarray[
'unitprice'];
2120 if ($this->prices_by_qty[$thirdparty_buyer->price_level]) {
2123 foreach ($this->prices_by_qty_list[$thirdparty_buyer->price_level] as $priceforthequantityarray) {
2124 if ($priceforthequantityarray[
'rowid'] != $pqp) {
2128 if ($priceforthequantityarray[
'price_base_type'] ==
'HT') {
2129 $pu_ht = $priceforthequantityarray[
'unitprice'];
2131 $pu_ttc = $priceforthequantityarray[
'unitprice'];
2138 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);
2155 public function get_buyprice($prodfournprice, $qty, $product_id = 0, $fourn_ref =
'', $fk_soc = 0)
2158 global $action, $hookmanager;
2161 if (is_object($hookmanager)) {
2162 $parameters = array(
2163 'prodfournprice' => $prodfournprice,
2165 'product_id' => $product_id,
2166 'fourn_ref' => $fourn_ref,
2167 'fk_soc' => $fk_soc,
2170 $reshook = $hookmanager->executeHooks(
'getBuyPrice', $parameters, $this, $action);
2172 return $hookmanager->resArray;
2179 $sql =
"SELECT pfp.rowid, pfp.price as price, pfp.quantity as quantity, pfp.remise_percent, pfp.fk_soc,";
2180 $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,";
2181 $sql .=
" pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code,";
2182 $sql .=
" pfp.packaging";
2183 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price as pfp";
2184 $sql .=
" WHERE pfp.rowid = ".((int) $prodfournprice);
2186 $sql .=
" AND pfp.quantity <= ".((float) $qty);
2188 $sql .=
" ORDER BY pfp.quantity DESC";
2190 dol_syslog(get_class($this).
"::get_buyprice first search by prodfournprice/qty", LOG_DEBUG);
2191 $resql = $this->db->query($sql);
2193 $obj = $this->db->fetch_object($resql);
2194 if ($obj && $obj->quantity > 0) {
2195 if (isModEnabled(
'dynamicprices') && !empty($obj->fk_supplier_price_expression)) {
2197 $prod_supplier->product_fourn_price_id = $obj->rowid;
2198 $prod_supplier->id = $obj->fk_product;
2199 $prod_supplier->fourn_qty = $obj->quantity;
2200 $prod_supplier->fourn_tva_tx = $obj->tva_tx;
2201 $prod_supplier->fk_supplier_price_expression = $obj->fk_supplier_price_expression;
2203 include_once DOL_DOCUMENT_ROOT.
'/product/dynamic_price/class/price_parser.class.php';
2205 $price_result = $priceparser->parseProductSupplier($prod_supplier);
2206 if ($price_result >= 0) {
2207 $obj->price = $price_result;
2210 $this->product_fourn_price_id = $obj->rowid;
2211 $this->buyprice = $obj->price;
2212 $this->fourn_pu = $obj->price / $obj->quantity;
2213 $this->fourn_price_base_type =
'HT';
2214 $this->fourn_socid = $obj->fk_soc;
2215 $this->ref_fourn = $obj->ref_supplier;
2216 $this->ref_supplier = $obj->ref_supplier;
2217 $this->desc_supplier = $obj->desc_supplier;
2218 $this->remise_percent = $obj->remise_percent;
2219 $this->vatrate_supplier = $obj->tva_tx;
2220 $this->default_vat_code_supplier = $obj->default_vat_code;
2221 $this->fourn_multicurrency_price = $obj->multicurrency_price;
2222 $this->fourn_multicurrency_unitprice = $obj->multicurrency_unitprice;
2223 $this->fourn_multicurrency_tx = $obj->multicurrency_tx;
2224 $this->fourn_multicurrency_id = $obj->fk_multicurrency;
2225 $this->fourn_multicurrency_code = $obj->multicurrency_code;
2227 $this->packaging = $obj->packaging;
2229 $result = $obj->fk_product;
2233 $sql =
"SELECT pfp.rowid, pfp.price as price, pfp.quantity as quantity, pfp.remise_percent, pfp.fk_soc,";
2234 $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,";
2235 $sql .=
" pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code,";
2236 $sql .=
" pfp.packaging";
2237 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price as pfp";
2238 $sql .=
" WHERE 1 = 1";
2239 if ($product_id > 0) {
2240 $sql .=
" AND pfp.fk_product = ".((int) $product_id);
2242 if ($fourn_ref !=
'none') {
2243 $sql .=
" AND pfp.ref_fourn = '".$this->db->escape($fourn_ref).
"'";
2246 $sql .=
" AND pfp.fk_soc = ".((int) $fk_soc);
2249 $sql .=
" AND pfp.quantity <= ".((float) $qty);
2251 $sql .=
" ORDER BY pfp.quantity DESC";
2254 dol_syslog(get_class($this).
"::get_buyprice second search from qty/ref/product_id", LOG_DEBUG);
2255 $resql = $this->db->query($sql);
2257 $obj = $this->db->fetch_object($resql);
2258 if ($obj && $obj->quantity > 0) {
2259 if (isModEnabled(
'dynamicprices') && !empty($obj->fk_supplier_price_expression)) {
2261 $prod_supplier->product_fourn_price_id = $obj->rowid;
2262 $prod_supplier->id = $obj->fk_product;
2263 $prod_supplier->fourn_qty = $obj->quantity;
2264 $prod_supplier->fourn_tva_tx = $obj->tva_tx;
2265 $prod_supplier->fk_supplier_price_expression = $obj->fk_supplier_price_expression;
2267 include_once DOL_DOCUMENT_ROOT.
'/product/dynamic_price/class/price_parser.class.php';
2269 $price_result = $priceparser->parseProductSupplier($prod_supplier);
2271 $obj->price = $price_result;
2274 $this->product_fourn_price_id = $obj->rowid;
2275 $this->buyprice = $obj->price;
2276 $this->fourn_qty = $obj->quantity;
2277 $this->fourn_pu = $obj->price / $obj->quantity;
2278 $this->fourn_price_base_type =
'HT';
2279 $this->fourn_socid = $obj->fk_soc;
2280 $this->ref_fourn = $obj->ref_supplier;
2281 $this->ref_supplier = $obj->ref_supplier;
2282 $this->desc_supplier = $obj->desc_supplier;
2283 $this->remise_percent = $obj->remise_percent;
2284 $this->vatrate_supplier = $obj->tva_tx;
2285 $this->default_vat_code_supplier = $obj->default_vat_code;
2286 $this->fourn_multicurrency_price = $obj->multicurrency_price;
2287 $this->fourn_multicurrency_unitprice = $obj->multicurrency_unitprice;
2288 $this->fourn_multicurrency_tx = $obj->multicurrency_tx;
2289 $this->fourn_multicurrency_id = $obj->fk_multicurrency;
2290 $this->fourn_multicurrency_code = $obj->multicurrency_code;
2292 $this->packaging = $obj->packaging;
2294 $result = $obj->fk_product;
2300 $this->error = $this->db->lasterror();
2305 $this->error = $this->db->lasterror();
2329 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)
2331 global $conf, $langs;
2337 dol_syslog(get_class($this).
"::update_price id=".$id.
" newprice=".$newprice.
" newpricebase=".$newpricebase.
" newminprice=".$newminprice.
" level=".$level.
" npr=".$newnpr.
" newdefaultvatcode=".$newdefaultvatcode);
2340 if (empty($this->tva_tx)) {
2343 if (empty($newnpr)) {
2346 if (empty($newminprice)) {
2351 if ($newvat ===
null || $newvat ==
'') {
2357 if ((
getDolGlobalString(
'PRODUIT_MULTIPRICES') ||
getDolGlobalString(
'PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) && !$ignore_autogen && $this->price_autogen && ($level == 1)) {
2358 return $this->
generateMultiprices($user, $newprice, $newpricebase, $newvat, $newnpr, $newpbq);
2361 if (!empty($newminprice) && ($newminprice > $newprice)) {
2362 $this->error =
'ErrorPriceCantBeLowerThanMinPrice';
2366 if ($newprice !==
'' || $newprice === 0) {
2367 if ($newpricebase ==
'TTC') {
2368 $price_ttc = (float)
price2num($newprice,
'MU');
2369 $price = (float)
price2num($newprice) / (1 + ((float) $newvat / 100));
2370 $price = (float)
price2num($price,
'MU');
2372 if ($newminprice !=
'' || $newminprice == 0) {
2373 $price_min_ttc = (float)
price2num($newminprice,
'MU');
2374 $price_min = (float)
price2num($newminprice) / (1 + ($newvat / 100));
2375 $price_min = (float)
price2num($price_min,
'MU');
2381 $price = (float)
price2num($newprice,
'MU');
2382 $price_ttc = ($newnpr != 1) ? (
float)
price2num($newprice) * (1 + ($newvat / 100)) : $price;
2383 $price_ttc = (float)
price2num($price_ttc,
'MU');
2385 if ($newminprice !==
'' || $newminprice === 0) {
2386 $price_min = (float)
price2num($newminprice,
'MU');
2387 $price_min_ttc = (float)
price2num($newminprice) * (1 + ($newvat / 100));
2388 $price_min_ttc = (float)
price2num($price_min_ttc,
'MU');
2397 if (count($localtaxes_array) > 0) {
2398 $localtaxtype1 = $localtaxes_array[
'0'];
2399 $localtax1 = $localtaxes_array[
'1'];
2400 $localtaxtype2 = $localtaxes_array[
'2'];
2401 $localtax2 = $localtaxes_array[
'3'];
2404 if (!empty($newdefaultvatcode)) {
2407 $sql =
"SELECT t.rowid, t.code, t.recuperableonly as tva_npr, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
2408 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_tva as t, ".MAIN_DB_PREFIX.
"c_country as c";
2409 $sql .=
" WHERE t.fk_pays = c.rowid AND c.code = '".$this->db->escape($mysoc->country_code).
"'";
2410 $sql .=
" AND t.taux = ".((float) $newdefaultvatcode).
" AND t.active = 1";
2411 $sql .=
" AND t.code = '".$this->db->escape($newdefaultvatcode).
"'";
2412 $resql = $this->db->query($sql);
2414 $obj = $this->db->fetch_object($resql);
2416 $npr = $obj->tva_npr;
2417 $localtax1 = $obj->localtax1;
2418 $localtax2 = $obj->localtax2;
2419 $localtaxtype1 = $obj->localtax1_type;
2420 $localtaxtype2 = $obj->localtax2_type;
2425 $localtaxtype1 =
'0';
2427 $localtaxtype2 =
'0';
2431 if (empty($localtax1)) {
2434 if (empty($localtax2)) {
2442 $sql =
"UPDATE ".$this->db->prefix().
"product SET";
2443 $sql .=
" price_base_type = '".$this->db->escape($newpricebase).
"',";
2444 $sql .=
" price = ".(float) $price.
",";
2445 $sql .=
" price_ttc = ".(float) $price_ttc.
",";
2446 $sql .=
" price_min = ".(float) $price_min.
",";
2447 $sql .=
" price_min_ttc = ".(float) $price_min_ttc.
",";
2448 $sql .=
" localtax1_tx = ".($localtax1 >= 0 ? (float) $localtax1 :
'NULL').
",";
2449 $sql .=
" localtax2_tx = ".($localtax2 >= 0 ? (float) $localtax2 :
'NULL').
",";
2450 $sql .=
" localtax1_type = ".($localtaxtype1 !=
'' ?
"'".$this->db->escape($localtaxtype1).
"'" :
"'0'").
",";
2451 $sql .=
" localtax2_type = ".($localtaxtype2 !=
'' ?
"'".$this->db->escape($localtaxtype2).
"'" :
"'0'").
",";
2452 $sql .=
" default_vat_code = ".($newdefaultvatcode ?
"'".$this->db->escape($newdefaultvatcode).
"'" :
"null").
",";
2453 $sql .=
" price_label = ".(!empty($price_label) ?
"'".$this->db->escape($price_label).
"'" :
"null").
",";
2454 $sql .=
" tva_tx = ".(float)
price2num($newvat).
",";
2455 $sql .=
" recuperableonly = '".$this->db->escape($newnpr).
"'";
2456 $sql .=
" WHERE rowid = ".((int) $id);
2458 dol_syslog(get_class($this).
"::update_price", LOG_DEBUG);
2459 $resql = $this->db->query($sql);
2461 $this->multiprices[$level] = $price;
2462 $this->multiprices_ttc[$level] = $price_ttc;
2463 $this->multiprices_min[$level] = $price_min;
2464 $this->multiprices_min_ttc[$level] = $price_min_ttc;
2465 $this->multiprices_base_type[$level] = $newpricebase;
2466 $this->multiprices_default_vat_code[$level] = $newdefaultvatcode;
2467 $this->multiprices_tva_tx[$level] = $newvat;
2468 $this->multiprices_recuperableonly[$level] = $newnpr;
2470 $this->
price = $price;
2471 $this->price_label = $price_label;
2472 $this->price_ttc = $price_ttc;
2473 $this->price_min = $price_min;
2474 $this->price_min_ttc = $price_min_ttc;
2475 $this->price_base_type = $newpricebase;
2476 $this->default_vat_code = $newdefaultvatcode;
2477 $this->tva_tx = $newvat;
2478 $this->tva_npr = $newnpr;
2481 $this->localtax1_tx = $localtax1;
2482 $this->localtax2_tx = $localtax2;
2483 $this->localtax1_type = $localtaxtype1;
2484 $this->localtax2_type = $localtaxtype2;
2487 $this->price_by_qty = $newpbq;
2491 if (!empty(array_diff_assoc($newPriceData, $lastPriceData)) || !
getDolGlobalString(
'PRODUIT_MULTIPRICES')) {
2495 $this->level = $level;
2499 $result = $this->
call_trigger(
'PRODUCT_PRICE_MODIFY', $user);
2501 $this->db->rollback();
2507 $this->db->commit();
2509 $this->db->rollback();
2510 $this->error = $this->db->lasterror();
2529 $this->fk_price_expression = $expression_id;
2531 return $this->
update($this->
id, $user);
2546 public function fetch($id = 0, $ref =
'', $ref_ext =
'', $barcode =
'', $ignore_expression = 0, $ignore_price_load = 0, $ignore_lang_load = 0)
2548 include_once DOL_DOCUMENT_ROOT.
'/core/lib/company.lib.php';
2550 global $langs, $conf;
2552 dol_syslog(get_class($this).
"::fetch id=".$id.
" ref=".$ref.
" ref_ext=".$ref_ext);
2555 if (!$id && !$ref && !$ref_ext && !$barcode) {
2556 $this->error =
'ErrorWrongParameters';
2557 dol_syslog(get_class($this).
"::fetch ".$this->error, LOG_ERR);
2561 $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,";
2562 $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,";
2563 $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,";
2564 $sql .=
" p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.last_main_doc,";
2565 $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,";
2567 $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,";
2569 $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,";
2574 $separatedEntityPMP =
false;
2575 $separatedStock =
false;
2576 $visibleWarehousesEntities = $conf->entity;
2579 $checkPMPPerEntity = $this->db->query(
"SELECT pmp FROM " . $this->db->prefix() .
"product_perentity WHERE fk_product = ".((int) $id).
" AND entity = ".(
int) $conf->entity);
2580 if ($this->db->num_rows($checkPMPPerEntity) > 0) {
2581 $separatedEntityPMP =
true;
2585 $separatedStock =
true;
2586 if (isset($mc->sharings[
'stock']) && !empty($mc->sharings[
'stock'])) {
2587 $visibleWarehousesEntities .=
"," . implode(
",", $mc->sharings[
'stock']);
2590 if ($separatedEntityPMP) {
2591 $sql .=
" ppe.pmp,";
2595 $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,";
2596 $sql .=
" p.fk_price_expression, p.price_autogen, p.model_pdf,";
2597 $sql .=
" p.price_label,";
2598 if ($separatedStock) {
2599 $sql .=
" SUM(sp.reel) as stock";
2603 $sql .=
" FROM ".$this->db->prefix().
"product as p";
2605 $sql .=
" LEFT JOIN " . $this->db->prefix() .
"product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity);
2607 if ($separatedStock) {
2608 $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).
"))";
2612 $sql .=
" WHERE p.rowid = ".((int) $id);
2614 $sql .=
" WHERE p.entity IN (".getEntity($this->element).
")";
2616 $sql .=
" AND p.ref = '".$this->db->escape($ref).
"'";
2617 } elseif ($ref_ext) {
2618 $sql .=
" AND p.ref_ext = '".$this->db->escape($ref_ext).
"'";
2619 } elseif ($barcode) {
2620 $sql .=
" AND p.barcode = '".$this->db->escape($barcode).
"'";
2623 if ($separatedStock) {
2624 $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,";
2625 $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,";
2626 $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,";
2627 $sql .=
" p.length, p.length_units, p.width, p.width_units, p.height, p.height_units,";
2628 $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,";
2630 $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,";
2632 $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,";
2634 if ($separatedEntityPMP) {
2635 $sql .=
" ppe.pmp,";
2639 $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,";
2640 $sql .=
" p.fk_price_expression, p.price_autogen, p.model_pdf";
2641 $sql .=
" ,p.price_label";
2642 if (!$separatedStock) {
2643 $sql .=
", p.stock";
2647 $resql = $this->db->query($sql);
2649 unset($this->oldcopy);
2651 if ($this->db->num_rows($resql) > 0) {
2652 $obj = $this->db->fetch_object($resql);
2654 $this->
id = $obj->rowid;
2655 $this->
ref = $obj->ref;
2656 $this->ref_ext = $obj->ref_ext;
2657 $this->label = $obj->label;
2659 $this->url = $obj->url;
2660 $this->note_public = $obj->note_public;
2661 $this->note_private = $obj->note_private;
2662 $this->note = $obj->note_private;
2664 $this->
type = $obj->fk_product_type;
2665 $this->price_label = $obj->price_label;
2666 $this->
status = $obj->tosell;
2667 $this->status_buy = $obj->tobuy;
2668 $this->status_batch = $obj->tobatch;
2669 $this->sell_or_eat_by_mandatory = $obj->sell_or_eat_by_mandatory;
2670 $this->batch_mask = $obj->batch_mask;
2672 $this->customcode = $obj->customcode;
2673 $this->country_id = $obj->fk_country;
2674 $this->country_code =
getCountry($this->country_id, 2, $this->db);
2675 $this->state_id = $obj->fk_state;
2676 $this->lifetime = $obj->lifetime;
2677 $this->qc_frequency = $obj->qc_frequency;
2678 $this->
price = $obj->price;
2679 $this->price_ttc = $obj->price_ttc;
2680 $this->price_min = $obj->price_min;
2681 $this->price_min_ttc = $obj->price_min_ttc;
2682 $this->price_base_type = $obj->price_base_type;
2683 $this->cost_price = isset($obj->cost_price) ? (float) $obj->cost_price :
null;
2684 $this->default_vat_code = $obj->default_vat_code;
2685 $this->tva_tx = $obj->tva_tx;
2687 $this->tva_npr = $obj->tva_npr;
2689 $this->localtax1_tx = $obj->localtax1_tx;
2690 $this->localtax2_tx = $obj->localtax2_tx;
2691 $this->localtax1_type = $obj->localtax1_type;
2692 $this->localtax2_type = $obj->localtax2_type;
2694 $this->finished = $obj->finished;
2695 $this->fk_default_bom = $obj->fk_default_bom;
2697 $this->duration = $obj->duration;
2698 $this->duration_value = $obj->duration ? (int) (substr($obj->duration, 0,
dol_strlen($obj->duration) - 1)) : 0;
2699 $this->duration_unit = $obj->duration ? substr($obj->duration, -1) :
null;
2700 $this->canvas = $obj->canvas;
2701 $this->net_measure = $obj->net_measure;
2702 $this->net_measure_units = $obj->net_measure_units;
2703 $this->weight = $obj->weight;
2704 $this->weight_units = (is_null($obj->weight_units) ? 0 : $obj->weight_units);
2705 $this->length = $obj->length;
2706 $this->length_units = (is_null($obj->length_units) ? 0 : $obj->length_units);
2707 $this->width = $obj->width;
2708 $this->width_units = (is_null($obj->width_units) ? 0 : $obj->width_units);
2709 $this->height = $obj->height;
2710 $this->height_units = (is_null($obj->height_units) ? 0 : $obj->height_units);
2712 $this->surface = $obj->surface;
2713 $this->surface_units = (is_null($obj->surface_units) ? 0 : $obj->surface_units);
2714 $this->volume = $obj->volume;
2715 $this->volume_units = (is_null($obj->volume_units) ? 0 : $obj->volume_units);
2716 $this->barcode = $obj->barcode;
2717 $this->barcode_type = $obj->fk_barcode_type;
2719 $this->accountancy_code_buy = $obj->accountancy_code_buy;
2720 $this->accountancy_code_buy_intra = $obj->accountancy_code_buy_intra;
2721 $this->accountancy_code_buy_export = $obj->accountancy_code_buy_export;
2722 $this->accountancy_code_sell = $obj->accountancy_code_sell;
2723 $this->accountancy_code_sell_intra = $obj->accountancy_code_sell_intra;
2724 $this->accountancy_code_sell_export = $obj->accountancy_code_sell_export;
2726 $this->fk_default_warehouse = $obj->fk_default_warehouse;
2727 $this->fk_default_workstation = $obj->fk_default_workstation;
2728 $this->seuil_stock_alerte = $obj->seuil_stock_alerte;
2729 $this->desiredstock = $obj->desiredstock;
2730 $this->stock_reel = $obj->stock;
2731 $this->pmp = $obj->pmp;
2733 $this->date_creation = $obj->datec;
2734 $this->date_modification = $obj->tms;
2735 $this->import_key = $obj->import_key;
2736 $this->entity = $obj->entity;
2738 $this->ref_ext = $obj->ref_ext;
2739 $this->fk_price_expression = $obj->fk_price_expression;
2740 $this->fk_unit = $obj->fk_unit;
2741 $this->price_autogen = $obj->price_autogen;
2742 $this->model_pdf = $obj->model_pdf;
2743 $this->last_main_doc = $obj->last_main_doc;
2745 $this->mandatory_period = $obj->mandatory_period;
2747 $this->db->free($resql);
2760 for ($i = 1; $i <= $maxi; $i++) {
2761 $sql =
"SELECT price, price_ttc, price_min, price_min_ttc,";
2762 $sql .=
" price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid, recuperableonly";
2763 $sql .=
" ,price_label";
2764 $sql .=
" FROM ".$this->db->prefix().
"product_price";
2765 $sql .=
" WHERE entity IN (".getEntity(
'productprice').
")";
2766 $sql .=
" AND price_level=".((int) $i);
2767 $sql .=
" AND fk_product = ".((int) $this->
id);
2768 $sql .=
" ORDER BY date_price DESC, rowid DESC";
2770 $resql = $this->db->query($sql);
2772 $result = $this->db->fetch_array($resql);
2774 $this->multiprices[$i] = $result ? $result[
"price"] :
null;
2775 $this->multiprices_ttc[$i] = $result ? $result[
"price_ttc"] :
null;
2776 $this->multiprices_min[$i] = $result ? $result[
"price_min"] :
null;
2777 $this->multiprices_min_ttc[$i] = $result ? $result[
"price_min_ttc"] :
null;
2778 $this->multiprices_base_type[$i] = $result ? $result[
"price_base_type"] :
null;
2780 $this->multiprices_tva_tx[$i] = $result ? $result[
"tva_tx"].($result ?
' ('.$result[
'default_vat_code'].
')' :
'') :
null;
2781 $this->multiprices_recuperableonly[$i] = $result ? $result[
"recuperableonly"] :
null;
2820 $this->error = $this->db->lasterror;
2824 } elseif (
getDolGlobalString(
'PRODUIT_CUSTOMER_PRICES') && empty($ignore_price_load)) {
2826 } elseif (
getDolGlobalString(
'PRODUIT_CUSTOMER_PRICES_BY_QTY') && empty($ignore_price_load)) {
2827 $sql =
"SELECT price, price_ttc, price_min, price_min_ttc,";
2828 $sql .=
" price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid";
2829 $sql .=
" FROM ".$this->db->prefix().
"product_price";
2830 $sql .=
" WHERE fk_product = ".((int) $this->
id);
2831 $sql .=
" ORDER BY date_price DESC, rowid DESC";
2834 $resql = $this->db->query($sql);
2836 $result = $this->db->fetch_array($resql);
2840 $this->prices_by_qty[0] = $result[
"price_by_qty"];
2841 $this->prices_by_qty_id[0] = $result[
"rowid"];
2843 if ($this->prices_by_qty[0] == 1) {
2844 $sql =
"SELECT rowid,price, unitprice, quantity, remise_percent, remise, remise, price_base_type";
2845 $sql .=
" FROM ".$this->db->prefix().
"product_price_by_qty";
2846 $sql .=
" WHERE fk_product_price = ".((int) $this->prices_by_qty_id[0]);
2847 $sql .=
" ORDER BY quantity ASC";
2849 $resql = $this->db->query($sql);
2851 $resultat = array();
2853 while ($result = $this->db->fetch_array($resql)) {
2854 $resultat[$ii] = array();
2855 $resultat[$ii][
"rowid"] = $result[
"rowid"];
2856 $resultat[$ii][
"price"] = $result[
"price"];
2857 $resultat[$ii][
"unitprice"] = $result[
"unitprice"];
2858 $resultat[$ii][
"quantity"] = $result[
"quantity"];
2859 $resultat[$ii][
"remise_percent"] = $result[
"remise_percent"];
2861 $resultat[$ii][
"price_base_type"] = $result[
"price_base_type"];
2864 $this->prices_by_qty_list[0] = $resultat;
2866 $this->error = $this->db->lasterror;
2872 $this->error = $this->db->lasterror;
2875 } elseif (
getDolGlobalString(
'PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') && empty($ignore_price_load)) {
2877 for ($i = 1; $i <= $maxi; $i++) {
2878 $sql =
"SELECT price, price_ttc, price_min, price_min_ttc,";
2879 $sql .=
" price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid, recuperableonly";
2880 $sql .=
" FROM ".$this->db->prefix().
"product_price";
2881 $sql .=
" WHERE entity IN (".getEntity(
'productprice').
")";
2882 $sql .=
" AND price_level=".((int) $i);
2883 $sql .=
" AND fk_product = ".((int) $this->
id);
2884 $sql .=
" ORDER BY date_price DESC, rowid DESC";
2886 $resql = $this->db->query($sql);
2888 $this->error = $this->db->lasterror;
2890 } elseif ($result = $this->db->fetch_array($resql)) {
2891 $this->multiprices[$i] = (!empty($result[
"price"]) ? $result[
"price"] : 0);
2892 $this->multiprices_ttc[$i] = (!empty($result[
"price_ttc"]) ? $result[
"price_ttc"] : 0);
2893 $this->multiprices_min[$i] = (!empty($result[
"price_min"]) ? $result[
"price_min"] : 0);
2894 $this->multiprices_min_ttc[$i] = (!empty($result[
"price_min_ttc"]) ? $result[
"price_min_ttc"] : 0);
2895 $this->multiprices_base_type[$i] = (!empty($result[
"price_base_type"]) ? $result[
"price_base_type"] :
'');
2897 $this->multiprices_tva_tx[$i] = (!empty($result[
"tva_tx"]) ? $result[
"tva_tx"] : 0);
2898 $this->multiprices_recuperableonly[$i] = (!empty($result[
"recuperableonly"]) ? $result[
"recuperableonly"] : 0);
2901 $this->prices_by_qty[$i] = (!empty($result[
"price_by_qty"]) ? $result[
"price_by_qty"] : 0);
2902 $this->prices_by_qty_id[$i] = (!empty($result[
"rowid"]) ? $result[
"rowid"] : 0);
2904 if ($this->prices_by_qty[$i] == 1) {
2905 $sql =
"SELECT rowid, price, unitprice, quantity, remise_percent, remise, price_base_type";
2906 $sql .=
" FROM ".$this->db->prefix().
"product_price_by_qty";
2907 $sql .=
" WHERE fk_product_price = ".((int) $this->prices_by_qty_id[$i]);
2908 $sql .=
" ORDER BY quantity ASC";
2910 $resql = $this->db->query($sql);
2912 $resultat = array();
2914 while ($result = $this->db->fetch_array($resql)) {
2915 $resultat[$ii] = array();
2916 $resultat[$ii][
"rowid"] = $result[
"rowid"];
2917 $resultat[$ii][
"price"] = $result[
"price"];
2918 $resultat[$ii][
"unitprice"] = $result[
"unitprice"];
2919 $resultat[$ii][
"quantity"] = $result[
"quantity"];
2920 $resultat[$ii][
"remise_percent"] = $result[
"remise_percent"];
2921 $resultat[$ii][
"remise"] = $result[
"remise"];
2922 $resultat[$ii][
"price_base_type"] = $result[
"price_base_type"];
2925 $this->prices_by_qty_list[$i] = $resultat;
2927 $this->error = $this->db->lasterror;
2935 if (isModEnabled(
'dynamicprices') && !empty($this->fk_price_expression) && empty($ignore_expression)) {
2936 include_once DOL_DOCUMENT_ROOT.
'/product/dynamic_price/class/price_parser.class.php';
2938 $price_result = $priceparser->parseProduct($this);
2939 if ($price_result >= 0) {
2940 $this->
price = $price_result;
2942 $this->price_ttc = (float)
price2num($this->
price) * (1 + ($this->tva_tx / 100));
2943 $this->price_ttc = (float)
price2num($this->price_ttc,
'MU');
2949 $this->stock_warehouse = array();
2956 $this->error = $this->db->lasterror();
2971 global $user, $hookmanager, $action;
2975 foreach (array(
'toconsume',
'consumed',
'toproduce',
'produced') as $role) {
2976 $this->stats_mo[
'customers_'.$role] = 0;
2977 $this->stats_mo[
'nb_'.$role] = 0;
2978 $this->stats_mo[
'qty_'.$role] = 0;
2980 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,";
2981 $sql .=
" SUM(mp.qty) as qty";
2982 $sql .=
" FROM ".$this->db->prefix().
"mrp_mo as c";
2983 $sql .=
" INNER JOIN ".$this->db->prefix().
"mrp_production as mp ON mp.fk_mo=c.rowid";
2984 if (!$user->hasRight(
'societe',
'client',
'voir')) {
2985 $sql .=
" INNER JOIN ".$this->db->prefix().
"societe_commerciaux as sc ON sc.fk_soc=c.fk_soc AND sc.fk_user = ".((int) $user->id);
2988 $sql .=
" c.entity IN (".getEntity(
'mo').
")";
2990 $sql .=
" AND mp.fk_product = ".((int) $this->
id);
2991 $sql .=
" AND mp.role ='".$this->db->escape($role).
"'";
2993 $sql .=
" AND c.fk_soc = ".((int) $socid);
2996 $result = $this->db->query($sql);
2998 $obj = $this->db->fetch_object($result);
2999 $this->stats_mo[
'customers_'.$role] = $obj->nb_customers ? $obj->nb_customers : 0;
3000 $this->stats_mo[
'nb_'.$role] = $obj->nb ? $obj->nb : 0;
3001 $this->stats_mo[
'qty_'.$role] = $obj->qty ?
price2num($obj->qty,
'MS') : 0;
3003 $this->error = $this->db->error();
3008 if (!empty($error)) {
3012 $parameters = array(
'socid' => $socid);
3013 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerMO', $parameters, $this, $action);
3015 $this->stats_mo = $hookmanager->resArray[
'stats_mo'];
3031 global $user, $hookmanager, $action;
3035 $this->stats_bom[
'nb_toproduce'] = 0;
3036 $this->stats_bom[
'nb_toconsume'] = 0;
3037 $this->stats_bom[
'qty_toproduce'] = 0;
3038 $this->stats_bom[
'qty_toconsume'] = 0;
3040 $sql =
"SELECT COUNT(DISTINCT b.rowid) as nb_toproduce,";
3041 $sql .=
" SUM(b.qty) as qty_toproduce";
3042 $sql .=
" FROM ".$this->db->prefix().
"bom_bom as b";
3043 $sql .=
" INNER JOIN ".$this->db->prefix().
"bom_bomline as bl ON bl.fk_bom=b.rowid";
3045 $sql .=
" b.entity IN (".getEntity(
'bom').
")";
3046 $sql .=
" AND b.fk_product =".((int) $this->
id);
3047 $sql .=
" GROUP BY b.rowid";
3049 $result = $this->db->query($sql);
3051 $obj = $this->db->fetch_object($result);
3052 $this->stats_bom[
'nb_toproduce'] = !empty($obj->nb_toproduce) ? $obj->nb_toproduce : 0;
3053 $this->stats_bom[
'qty_toproduce'] = !empty($obj->qty_toproduce) ?
price2num($obj->qty_toproduce) : 0;
3055 $this->error = $this->db->error();
3059 $sql =
"SELECT COUNT(DISTINCT bl.rowid) as nb_toconsume,";
3060 $sql .=
" SUM(bl.qty) as qty_toconsume";
3061 $sql .=
" FROM ".$this->db->prefix().
"bom_bom as b";
3062 $sql .=
" INNER JOIN ".$this->db->prefix().
"bom_bomline as bl ON bl.fk_bom=b.rowid";
3064 $sql .=
" b.entity IN (".getEntity(
'bom').
")";
3065 $sql .=
" AND bl.fk_product =".((int) $this->
id);
3067 $result = $this->db->query($sql);
3069 $obj = $this->db->fetch_object($result);
3070 $this->stats_bom[
'nb_toconsume'] = !empty($obj->nb_toconsume) ? $obj->nb_toconsume : 0;
3071 $this->stats_bom[
'qty_toconsume'] = !empty($obj->qty_toconsume) ?
price2num($obj->qty_toconsume) : 0;
3073 $this->error = $this->db->error();
3077 if (!empty($error)) {
3081 $parameters = array(
'socid' => $socid);
3082 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerMO', $parameters, $this, $action);
3084 $this->stats_bom = $hookmanager->resArray[
'stats_bom'];
3100 global $conf, $user, $hookmanager, $action;
3102 $sql =
"SELECT COUNT(DISTINCT p.fk_soc) as nb_customers, COUNT(DISTINCT p.rowid) as nb,";
3103 $sql .=
" COUNT(pd.rowid) as nb_rows, SUM(pd.qty) as qty";
3104 $sql .=
" FROM ".$this->db->prefix().
"propaldet as pd";
3105 $sql .=
", ".$this->db->prefix().
"propal as p";
3106 $sql .=
", ".$this->db->prefix().
"societe as s";
3107 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3108 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3110 $sql .=
" WHERE p.rowid = pd.fk_propal";
3111 $sql .=
" AND p.fk_soc = s.rowid";
3112 $sql .=
" AND p.entity IN (".getEntity(
'propal').
")";
3113 $sql .=
" AND pd.fk_product = ".((int) $this->
id);
3114 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3115 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3119 $sql .=
" AND p.fk_soc = ".((int) $socid);
3122 $result = $this->db->query($sql);
3124 $obj = $this->db->fetch_object($result);
3125 $this->stats_propale[
'customers'] = $obj->nb_customers;
3126 $this->stats_propale[
'nb'] = $obj->nb;
3127 $this->stats_propale[
'rows'] = $obj->nb_rows;
3128 $this->stats_propale[
'qty'] = $obj->qty ? $obj->qty : 0;
3133 if (is_array($TFather) && !empty($TFather)) {
3134 foreach ($TFather as &$fatherData) {
3135 $pFather =
new Product($this->db);
3136 $pFather->id = $fatherData[
'id'];
3137 $qtyCoef = $fatherData[
'qty'];
3139 if ($fatherData[
'incdec']) {
3140 $pFather->load_stats_propale($socid);
3142 $this->stats_propale[
'customers'] += $pFather->stats_propale[
'customers'];
3143 $this->stats_propale[
'nb'] += $pFather->stats_propale[
'nb'];
3144 $this->stats_propale[
'rows'] += $pFather->stats_propale[
'rows'];
3145 $this->stats_propale[
'qty'] += $pFather->stats_propale[
'qty'] * $qtyCoef;
3151 $parameters = array(
'socid' => $socid);
3152 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerProposal', $parameters, $this, $action);
3154 $this->stats_propale = $hookmanager->resArray[
'stats_propale'];
3159 $this->error = $this->db->error();
3175 global $conf, $user, $hookmanager, $action;
3177 $sql =
"SELECT COUNT(DISTINCT p.fk_soc) as nb_suppliers, COUNT(DISTINCT p.rowid) as nb,";
3178 $sql .=
" COUNT(pd.rowid) as nb_rows, SUM(pd.qty) as qty";
3179 $sql .=
" FROM ".$this->db->prefix().
"supplier_proposaldet as pd";
3180 $sql .=
", ".$this->db->prefix().
"supplier_proposal as p";
3181 $sql .=
", ".$this->db->prefix().
"societe as s";
3182 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3183 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3185 $sql .=
" WHERE p.rowid = pd.fk_supplier_proposal";
3186 $sql .=
" AND p.fk_soc = s.rowid";
3187 $sql .=
" AND p.entity IN (".getEntity(
'supplier_proposal').
")";
3188 $sql .=
" AND pd.fk_product = ".((int) $this->
id);
3189 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3190 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3194 $sql .=
" AND p.fk_soc = ".((int) $socid);
3197 $result = $this->db->query($sql);
3199 $obj = $this->db->fetch_object($result);
3200 $this->stats_proposal_supplier[
'suppliers'] = $obj->nb_suppliers;
3201 $this->stats_proposal_supplier[
'nb'] = $obj->nb;
3202 $this->stats_proposal_supplier[
'rows'] = $obj->nb_rows;
3203 $this->stats_proposal_supplier[
'qty'] = $obj->qty ? $obj->qty : 0;
3205 $parameters = array(
'socid' => $socid);
3206 $reshook = $hookmanager->executeHooks(
'loadStatsSupplierProposal', $parameters, $this, $action);
3208 $this->stats_proposal_supplier = $hookmanager->resArray[
'stats_proposal_supplier'];
3213 $this->error = $this->db->error();
3231 global $conf, $user, $hookmanager, $action;
3233 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,";
3234 $sql .=
" COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty";
3235 $sql .=
" FROM ".$this->db->prefix().
"commandedet as cd";
3236 $sql .=
", ".$this->db->prefix().
"commande as c";
3237 $sql .=
", ".$this->db->prefix().
"societe as s";
3238 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3239 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3241 $sql .=
" WHERE c.rowid = cd.fk_commande";
3242 $sql .=
" AND c.fk_soc = s.rowid";
3243 $sql .=
" AND c.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'commande').
")";
3244 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
3245 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3246 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3249 $sql .=
" AND c.fk_soc = ".((int) $socid);
3251 if ($filtrestatut !=
'') {
3252 $sql .=
" AND c.fk_statut IN (".$this->db->sanitize($filtrestatut).
")";
3255 $result = $this->db->query($sql);
3257 $obj = $this->db->fetch_object($result);
3258 $this->stats_commande[
'customers'] = $obj->nb_customers;
3259 $this->stats_commande[
'nb'] = $obj->nb;
3260 $this->stats_commande[
'rows'] = $obj->nb_rows;
3261 $this->stats_commande[
'qty'] = $obj->qty ? $obj->qty : 0;
3266 if (is_array($TFather) && !empty($TFather)) {
3267 foreach ($TFather as &$fatherData) {
3268 $pFather =
new Product($this->db);
3269 $pFather->id = $fatherData[
'id'];
3270 $qtyCoef = $fatherData[
'qty'];
3272 if ($fatherData[
'incdec']) {
3273 $pFather->load_stats_commande($socid, $filtrestatut);
3275 $this->stats_commande[
'customers'] += $pFather->stats_commande[
'customers'];
3276 $this->stats_commande[
'nb'] += $pFather->stats_commande[
'nb'];
3277 $this->stats_commande[
'rows'] += $pFather->stats_commande[
'rows'];
3278 $this->stats_commande[
'qty'] += $pFather->stats_commande[
'qty'] * $qtyCoef;
3290 $sql =
"SELECT SUM(".$this->db->ifsql(
'f.type=2', -1, 1).
" * fd.qty) as count FROM ".$this->db->prefix().
"facturedet as fd ";
3291 $sql .=
" JOIN ".$this->db->prefix().
"facture as f ON fd.fk_facture = f.rowid";
3292 $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'))";
3293 $sql .=
" JOIN ".$this->db->prefix().
"commande as c ON el.fk_source = c.rowid";
3294 $sql .=
" WHERE c.fk_statut IN (".$this->db->sanitize($filtrestatut).
") AND c.facture = 0 AND fd.fk_product = ".((int) $this->
id);
3296 dol_syslog(__METHOD__.
":: sql $sql", LOG_NOTICE);
3297 $resql = $this->db->query($sql);
3299 if ($this->db->num_rows($resql) > 0) {
3300 $obj = $this->db->fetch_object($resql);
3301 $adeduire += $obj->count;
3305 $this->stats_commande[
'qty'] -= $adeduire;
3308 include_once DOL_DOCUMENT_ROOT.
'/compta/facture/class/facture.class.php';
3312 $sql =
"SELECT sum(".$this->db->ifsql(
'f.type=2', -1, 1).
" * fd.qty) as count FROM ".MAIN_DB_PREFIX.
"facturedet as fd ";
3313 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"facture as f ON fd.fk_facture = f.rowid";
3314 $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'))";
3315 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"commande as c ON el.fk_source = c.rowid";
3316 $sql .=
" WHERE c.fk_statut IN (".$this->db->sanitize($filtrestatut).
") AND f.fk_statut > ".
Facture::STATUS_DRAFT.
" AND fd.fk_product = ".((int) $this->
id);
3318 dol_syslog(__METHOD__.
":: sql $sql", LOG_NOTICE);
3319 $resql = $this->db->query($sql);
3321 if ($this->db->num_rows($resql) > 0) {
3322 $obj = $this->db->fetch_object($resql);
3323 $adeduire += $obj->count;
3326 $this->error = $this->db->error();
3330 $this->stats_commande[
'qty'] -= $adeduire;
3334 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3335 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerOrder', $parameters, $this, $action);
3337 $this->stats_commande = $hookmanager->resArray[
'stats_commande'];
3341 $this->error = $this->db->error();
3359 global $conf, $user, $hookmanager, $action;
3361 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_suppliers, COUNT(DISTINCT c.rowid) as nb,";
3362 $sql .=
" COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty";
3363 $sql .=
" FROM ".$this->db->prefix().
"commande_fournisseurdet as cd";
3364 $sql .=
", ".$this->db->prefix().
"commande_fournisseur as c";
3365 $sql .=
", ".$this->db->prefix().
"societe as s";
3366 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3367 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3369 $sql .=
" WHERE c.rowid = cd.fk_commande";
3370 $sql .=
" AND c.fk_soc = s.rowid";
3371 $sql .=
" AND c.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'supplier_order').
")";
3372 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
3373 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3374 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3377 $sql .=
" AND c.fk_soc = ".((int) $socid);
3379 if ($filtrestatut !=
'') {
3380 $sql .=
" AND c.fk_statut in (".$this->db->sanitize($filtrestatut).
")";
3382 if (!empty($dateofvirtualstock)) {
3383 $sql .=
" AND c.date_livraison <= '".$this->db->idate($dateofvirtualstock).
"'";
3386 $result = $this->db->query($sql);
3388 $obj = $this->db->fetch_object($result);
3389 $this->stats_commande_fournisseur[
'suppliers'] = $obj->nb_suppliers;
3390 $this->stats_commande_fournisseur[
'nb'] = $obj->nb;
3391 $this->stats_commande_fournisseur[
'rows'] = $obj->nb_rows;
3392 $this->stats_commande_fournisseur[
'qty'] = $obj->qty ? $obj->qty : 0;
3394 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3395 $reshook = $hookmanager->executeHooks(
'loadStatsSupplierOrder', $parameters, $this, $action);
3397 $this->stats_commande_fournisseur = $hookmanager->resArray[
'stats_commande_fournisseur'];
3402 $this->error = $this->db->error().
' sql='.$sql;
3417 public function load_stats_sending($socid = 0, $filtrestatut =
'', $forVirtualStock = 0, $filterShipmentStatus =
'')
3420 global $conf, $user, $hookmanager, $action;
3422 $sql =
"SELECT COUNT(DISTINCT e.fk_soc) as nb_customers, COUNT(DISTINCT e.rowid) as nb,";
3423 $sql .=
" COUNT(ed.rowid) as nb_rows, SUM(ed.qty) as qty";
3424 $sql .=
" FROM ".$this->db->prefix().
"expeditiondet as ed";
3425 $sql .=
", ".$this->db->prefix().
"commandedet as cd";
3426 $sql .=
", ".$this->db->prefix().
"commande as c";
3427 $sql .=
", ".$this->db->prefix().
"expedition as e";
3428 $sql .=
", ".$this->db->prefix().
"societe as s";
3429 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3430 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3432 $sql .=
" WHERE e.rowid = ed.fk_expedition";
3433 $sql .=
" AND c.rowid = cd.fk_commande";
3434 $sql .=
" AND e.fk_soc = s.rowid";
3435 $sql .=
" AND e.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'expedition').
")";
3436 $sql .=
" AND ed.fk_elementdet = cd.rowid";
3437 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
3438 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3439 $sql .=
" AND e.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3442 $sql .=
" AND e.fk_soc = ".((int) $socid);
3444 if ($filtrestatut !=
'') {
3445 $sql .=
" AND c.fk_statut IN (".$this->db->sanitize($filtrestatut).
")";
3447 if (!empty($filterShipmentStatus)) {
3448 $sql .=
" AND e.fk_statut IN (".$this->db->sanitize($filterShipmentStatus).
")";
3451 $result = $this->db->query($sql);
3453 $obj = $this->db->fetch_object($result);
3454 $this->stats_expedition[
'customers'] = $obj->nb_customers;
3455 $this->stats_expedition[
'nb'] = $obj->nb;
3456 $this->stats_expedition[
'rows'] = $obj->nb_rows;
3457 $this->stats_expedition[
'qty'] = $obj->qty ? $obj->qty : 0;
3462 if (is_array($TFather) && !empty($TFather)) {
3463 foreach ($TFather as &$fatherData) {
3464 $pFather =
new Product($this->db);
3465 $pFather->id = $fatherData[
'id'];
3466 $qtyCoef = $fatherData[
'qty'];
3468 if ($fatherData[
'incdec']) {
3469 $pFather->load_stats_sending($socid, $filtrestatut, $forVirtualStock);
3471 $this->stats_expedition[
'customers'] += $pFather->stats_expedition[
'customers'];
3472 $this->stats_expedition[
'nb'] += $pFather->stats_expedition[
'nb'];
3473 $this->stats_expedition[
'rows'] += $pFather->stats_expedition[
'rows'];
3474 $this->stats_expedition[
'qty'] += $pFather->stats_expedition[
'qty'] * $qtyCoef;
3480 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock,
'filterShipmentStatus' => $filterShipmentStatus);
3481 $reshook = $hookmanager->executeHooks(
'loadStatsSending', $parameters, $this, $action);
3483 $this->stats_expedition = $hookmanager->resArray[
'stats_expedition'];
3488 $this->error = $this->db->error();
3503 public function load_stats_reception($socid = 0, $filtrestatut =
'', $forVirtualStock = 0, $dateofvirtualstock =
null)
3506 global $conf, $user, $hookmanager, $action;
3508 $sql =
"SELECT COUNT(DISTINCT cf.fk_soc) as nb_suppliers, COUNT(DISTINCT cf.rowid) as nb,";
3509 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(fd.qty) as qty";
3510 $sql .=
" FROM ".$this->db->prefix().
"receptiondet_batch as fd";
3511 $sql .=
", ".$this->db->prefix().
"commande_fournisseur as cf";
3512 $sql .=
", ".$this->db->prefix().
"societe as s";
3513 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3514 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3516 $sql .=
" WHERE cf.rowid = fd.fk_element";
3517 $sql .=
" AND cf.fk_soc = s.rowid";
3518 $sql .=
" AND cf.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'supplier_order').
")";
3519 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
3520 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3521 $sql .=
" AND cf.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3524 $sql .=
" AND cf.fk_soc = ".((int) $socid);
3526 if ($filtrestatut !=
'') {
3527 $sql .=
" AND cf.fk_statut IN (".$this->db->sanitize($filtrestatut).
")";
3529 if (!empty($dateofvirtualstock)) {
3530 $sql .=
" AND fd.datec <= '".$this->db->idate($dateofvirtualstock).
"'";
3533 $result = $this->db->query($sql);
3535 $obj = $this->db->fetch_object($result);
3536 $this->stats_reception[
'suppliers'] = $obj->nb_suppliers;
3537 $this->stats_reception[
'nb'] = $obj->nb;
3538 $this->stats_reception[
'rows'] = $obj->nb_rows;
3539 $this->stats_reception[
'qty'] = $obj->qty ? $obj->qty : 0;
3541 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3542 $reshook = $hookmanager->executeHooks(
'loadStatsReception', $parameters, $this, $action);
3544 $this->stats_reception = $hookmanager->resArray[
'stats_reception'];
3549 $this->error = $this->db->error();
3565 public function load_stats_inproduction($socid = 0, $filtrestatut =
'', $forVirtualStock = 0, $dateofvirtualstock =
null, $warehouseid = 0)
3568 global $user, $hookmanager, $action;
3570 $serviceStockIsEnabled = isModEnabled(
"service") &&
getDolGlobalString(
'STOCK_SUPPORTS_SERVICES');
3572 $sql =
"SELECT COUNT(DISTINCT m.fk_soc) as nb_customers, COUNT(DISTINCT m.rowid) as nb,";
3573 $sql .=
" COUNT(mp.rowid) as nb_rows, SUM(mp.qty) as qty, role";
3574 $sql .=
" FROM ".$this->db->prefix().
"mrp_production as mp";
3575 $sql .=
", ".$this->db->prefix().
"mrp_mo as m";
3576 $sql .=
" LEFT JOIN ".$this->db->prefix().
"societe as s ON s.rowid = m.fk_soc";
3577 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3578 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3580 $sql .=
" WHERE m.rowid = mp.fk_mo";
3581 $sql .=
" AND m.entity IN (".getEntity(($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE')) ?
'stock' :
'mrp').
")";
3582 $sql .=
" AND mp.fk_product = ".((int) $this->
id);
3583 $sql .=
" AND (mp.disable_stock_change IN (0) OR mp.disable_stock_change IS NULL)";
3584 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3585 $sql .=
" AND m.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3588 $sql .=
" AND m.fk_soc = ".((int) $socid);
3590 if ($filtrestatut !=
'') {
3591 $sql .=
" AND m.status IN (".$this->db->sanitize($filtrestatut).
")";
3593 if (!empty($dateofvirtualstock)) {
3594 $sql .=
" AND m.date_valid <= '".$this->db->idate($dateofvirtualstock).
"'";
3596 if (!$serviceStockIsEnabled) {
3597 $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))";
3599 if (!empty($warehouseid)) {
3600 $sql .=
" AND m.fk_warehouse = ".((int) $warehouseid);
3602 $sql .=
" GROUP BY role";
3605 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] = 0;
3607 $this->stats_mrptoconsume[
'customers'] = 0;
3608 $this->stats_mrptoconsume[
'nb'] = 0;
3609 $this->stats_mrptoconsume[
'rows'] = 0;
3610 $this->stats_mrptoconsume[
'qty'] = 0;
3611 $this->stats_mrptoproduce[
'customers'] = 0;
3612 $this->stats_mrptoproduce[
'nb'] = 0;
3613 $this->stats_mrptoproduce[
'rows'] = 0;
3614 $this->stats_mrptoproduce[
'qty'] = 0;
3617 $result = $this->db->query($sql);
3619 while ($obj = $this->db->fetch_object($result)) {
3620 if ($obj->role ==
'toconsume' && empty($warehouseid)) {
3621 $this->stats_mrptoconsume[
'customers'] += $obj->nb_customers;
3622 $this->stats_mrptoconsume[
'nb'] += $obj->nb;
3623 $this->stats_mrptoconsume[
'rows'] += $obj->nb_rows;
3624 $this->stats_mrptoconsume[
'qty'] += ($obj->qty ? $obj->qty : 0);
3626 if ($obj->role ==
'consumed' && empty($warehouseid)) {
3630 $this->stats_mrptoconsume[
'qty'] -= ($obj->qty ? $obj->qty : 0);
3632 if ($obj->role ==
'toproduce') {
3634 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] += ($obj->qty ? $obj->qty : 0);
3636 $this->stats_mrptoproduce[
'customers'] += $obj->nb_customers;
3637 $this->stats_mrptoproduce[
'nb'] += $obj->nb;
3638 $this->stats_mrptoproduce[
'rows'] += $obj->nb_rows;
3639 $this->stats_mrptoproduce[
'qty'] += ($obj->qty ? $obj->qty : 0);
3642 if ($obj->role ==
'produced') {
3647 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] -= ($obj->qty ? $obj->qty : 0);
3649 $this->stats_mrptoproduce[
'qty'] -= ($obj->qty ? $obj->qty : 0);
3656 if ($this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] < 0) {
3657 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] = 0;
3660 if ($this->stats_mrptoconsume[
'qty'] < 0) {
3661 $this->stats_mrptoconsume[
'qty'] = 0;
3663 if ($this->stats_mrptoproduce[
'qty'] < 0) {
3664 $this->stats_mrptoproduce[
'qty'] = 0;
3668 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3669 $reshook = $hookmanager->executeHooks(
'loadStatsInProduction', $parameters, $this, $action);
3671 $this->stats_mrptoproduce = $hookmanager->resArray[
'stats_mrptoproduce'];
3676 $this->error = $this->db->error();
3691 global $conf, $user, $hookmanager, $action;
3693 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,";
3694 $sql .=
" COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty";
3695 $sql .=
" FROM ".$this->db->prefix().
"contratdet as cd";
3696 $sql .=
", ".$this->db->prefix().
"contrat as c";
3697 $sql .=
", ".$this->db->prefix().
"societe as s";
3698 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3699 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3701 $sql .=
" WHERE c.rowid = cd.fk_contrat";
3702 $sql .=
" AND c.fk_soc = s.rowid";
3703 $sql .=
" AND c.entity IN (".getEntity(
'contract').
")";
3704 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
3705 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3706 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3710 $sql .=
" AND c.fk_soc = ".((int) $socid);
3713 $result = $this->db->query($sql);
3715 $obj = $this->db->fetch_object($result);
3716 $this->stats_contrat[
'customers'] = $obj->nb_customers;
3717 $this->stats_contrat[
'nb'] = $obj->nb;
3718 $this->stats_contrat[
'rows'] = $obj->nb_rows;
3719 $this->stats_contrat[
'qty'] = $obj->qty ? $obj->qty : 0;
3724 if (is_array($TFather) && !empty($TFather)) {
3725 foreach ($TFather as &$fatherData) {
3726 $pFather =
new Product($this->db);
3727 $pFather->id = $fatherData[
'id'];
3728 $qtyCoef = $fatherData[
'qty'];
3730 if ($fatherData[
'incdec']) {
3731 $pFather->load_stats_contrat($socid);
3733 $this->stats_contrat[
'customers'] += $pFather->stats_contrat[
'customers'];
3734 $this->stats_contrat[
'nb'] += $pFather->stats_contrat[
'nb'];
3735 $this->stats_contrat[
'rows'] += $pFather->stats_contrat[
'rows'];
3736 $this->stats_contrat[
'qty'] += $pFather->stats_contrat[
'qty'] * $qtyCoef;
3742 $parameters = array(
'socid' => $socid);
3743 $reshook = $hookmanager->executeHooks(
'loadStatsContract', $parameters, $this, $action);
3745 $this->stats_contrat = $hookmanager->resArray[
'stats_contrat'];
3750 $this->error = $this->db->error().
' sql='.$sql;
3765 global $conf, $user, $hookmanager, $action;
3767 $sql =
"SELECT COUNT(DISTINCT f.fk_soc) as nb_customers, COUNT(DISTINCT f.rowid) as nb,";
3768 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(".$this->db->ifsql(
'f.type != 2',
'fd.qty',
'fd.qty * -1').
") as qty";
3769 $sql .=
" FROM ".$this->db->prefix().
"facturedet as fd";
3770 $sql .=
", ".$this->db->prefix().
"facture as f";
3771 $sql .=
", ".$this->db->prefix().
"societe as s";
3772 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3773 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3775 $sql .=
" WHERE f.rowid = fd.fk_facture";
3776 $sql .=
" AND f.fk_soc = s.rowid";
3777 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
3778 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
3779 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3780 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3784 $sql .=
" AND f.fk_soc = ".((int) $socid);
3787 $result = $this->db->query($sql);
3789 $obj = $this->db->fetch_object($result);
3790 $this->stats_facture[
'customers'] = $obj->nb_customers;
3791 $this->stats_facture[
'nb'] = $obj->nb;
3792 $this->stats_facture[
'rows'] = $obj->nb_rows;
3793 $this->stats_facture[
'qty'] = $obj->qty ? $obj->qty : 0;
3798 if (is_array($TFather) && !empty($TFather)) {
3799 foreach ($TFather as &$fatherData) {
3800 $pFather =
new Product($this->db);
3801 $pFather->id = $fatherData[
'id'];
3802 $qtyCoef = $fatherData[
'qty'];
3804 if ($fatherData[
'incdec']) {
3805 $pFather->load_stats_facture($socid);
3807 $this->stats_facture[
'customers'] += $pFather->stats_facture[
'customers'];
3808 $this->stats_facture[
'nb'] += $pFather->stats_facture[
'nb'];
3809 $this->stats_facture[
'rows'] += $pFather->stats_facture[
'rows'];
3810 $this->stats_facture[
'qty'] += $pFather->stats_facture[
'qty'] * $qtyCoef;
3816 $parameters = array(
'socid' => $socid);
3817 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerInvoice', $parameters, $this, $action);
3819 $this->stats_facture = $hookmanager->resArray[
'stats_facture'];
3824 $this->error = $this->db->error();
3840 global $conf, $user, $hookmanager, $action;
3842 $sql =
"SELECT COUNT(DISTINCT f.fk_soc) as nb_customers, COUNT(DISTINCT f.rowid) as nb,";
3843 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(fd.qty) as qty";
3844 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facturedet_rec as fd";
3845 $sql .=
", ".MAIN_DB_PREFIX.
"facture_rec as f";
3846 $sql .=
", ".MAIN_DB_PREFIX.
"societe as s";
3847 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3848 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
3850 $sql .=
" WHERE f.rowid = fd.fk_facture";
3851 $sql .=
" AND f.fk_soc = s.rowid";
3852 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
3853 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
3854 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3855 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3859 $sql .=
" AND f.fk_soc = ".((int) $socid);
3862 $result = $this->db->query($sql);
3864 $obj = $this->db->fetch_object($result);
3865 $this->stats_facturerec[
'customers'] = $obj->nb_customers;
3866 $this->stats_facturerec[
'nb'] = $obj->nb;
3867 $this->stats_facturerec[
'rows'] = $obj->nb_rows;
3868 $this->stats_facturerec[
'qty'] = $obj->qty ? $obj->qty : 0;
3873 if (is_array($TFather) && !empty($TFather)) {
3874 foreach ($TFather as &$fatherData) {
3875 $pFather =
new Product($this->db);
3876 $pFather->id = $fatherData[
'id'];
3877 $qtyCoef = $fatherData[
'qty'];
3879 if ($fatherData[
'incdec']) {
3880 $pFather->load_stats_facture($socid);
3882 $this->stats_facturerec[
'customers'] += $pFather->stats_facturerec[
'customers'];
3883 $this->stats_facturerec[
'nb'] += $pFather->stats_facturerec[
'nb'];
3884 $this->stats_facturerec[
'rows'] += $pFather->stats_facturerec[
'rows'];
3885 $this->stats_facturerec[
'qty'] += $pFather->stats_facturerec[
'qty'] * $qtyCoef;
3891 $parameters = array(
'socid' => $socid);
3892 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerInvoiceRec', $parameters, $this, $action);
3894 $this->stats_facturerec = $hookmanager->resArray[
'stats_facturerec'];
3899 $this->error = $this->db->error();
3914 global $conf, $user, $hookmanager, $action;
3916 $sql =
"SELECT COUNT(DISTINCT f.fk_soc) as nb_suppliers, COUNT(DISTINCT f.rowid) as nb,";
3917 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(fd.qty) as qty";
3918 $sql .=
" FROM ".$this->db->prefix().
"facture_fourn_det as fd";
3919 $sql .=
", ".$this->db->prefix().
"facture_fourn as f";
3920 $sql .=
", ".$this->db->prefix().
"societe as s";
3921 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3922 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3924 $sql .=
" WHERE f.rowid = fd.fk_facture_fourn";
3925 $sql .=
" AND f.fk_soc = s.rowid";
3926 $sql .=
" AND f.entity IN (".getEntity(
'facture_fourn').
")";
3927 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
3928 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3929 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3933 $sql .=
" AND f.fk_soc = ".((int) $socid);
3936 $result = $this->db->query($sql);
3938 $obj = $this->db->fetch_object($result);
3939 $this->stats_facture_fournisseur[
'suppliers'] = $obj->nb_suppliers;
3940 $this->stats_facture_fournisseur[
'nb'] = $obj->nb;
3941 $this->stats_facture_fournisseur[
'rows'] = $obj->nb_rows;
3942 $this->stats_facture_fournisseur[
'qty'] = $obj->qty ? $obj->qty : 0;
3944 $parameters = array(
'socid' => $socid);
3945 $reshook = $hookmanager->executeHooks(
'loadStatsSupplierInvoice', $parameters, $this, $action);
3947 $this->stats_facture_fournisseur = $hookmanager->resArray[
'stats_facture_fournisseur'];
3952 $this->error = $this->db->error();
3971 $resql = $this->db->query($sql);
3973 $num = $this->db->num_rows($resql);
3976 $arr = $this->db->fetch_array($resql);
3977 if (is_array($arr)) {
3978 $keyfortab = (string) $arr[1];
3980 $keyfortab = substr($keyfortab, -2);
3983 if ($mode ==
'byunit') {
3984 $tab[$keyfortab] = (empty($tab[$keyfortab]) ? 0 : $tab[$keyfortab]) + $arr[0];
3985 } elseif ($mode ==
'bynumber') {
3986 $tab[$keyfortab] = (empty($tab[$keyfortab]) ? 0 : $tab[$keyfortab]) + $arr[2];
3987 } elseif ($mode ==
'byamount') {
3988 $tab[$keyfortab] = (empty($tab[$keyfortab]) ? 0 : $tab[$keyfortab]) + $arr[2];
3997 $this->error = $this->db->error().
' sql='.$sql;
4004 } elseif ($year == -1) {
4013 for ($j = 0; $j < 12; $j++) {
4015 $idx = ucfirst(
dol_trunc(
dol_print_date(
dol_mktime(12, 0, 0, $month, 1, 1970),
"%b"), 1,
'right',
'UTF-8', 1));
4018 $result[$j] = array($idx, isset($tab[$year.$month]) ? $tab[$year.$month] : 0);
4021 $month =
"0".($month - 1);
4023 $month = substr($month, 1);
4031 return array_reverse($result);
4046 public function get_nb_vente($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4052 $sql =
"SELECT sum(d.qty) as qty, date_format(f.datef, '%Y%m')";
4053 if ($mode ==
'bynumber') {
4054 $sql .=
", count(DISTINCT f.rowid)";
4056 $sql .=
", sum(d.total_ht) as total_ht";
4057 $sql .=
" FROM ".$this->db->prefix().
"facturedet as d, ".$this->db->prefix().
"facture as f, ".$this->db->prefix().
"societe as s";
4058 if ($filteronproducttype >= 0) {
4059 $sql .=
", ".$this->db->prefix().
"product as p";
4061 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4062 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4064 $sql .=
" WHERE f.rowid = d.fk_facture";
4065 if ($this->
id > 0) {
4066 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4068 $sql .=
" AND d.fk_product > 0";
4070 if ($filteronproducttype >= 0) {
4071 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4073 $sql .=
" AND f.fk_soc = s.rowid";
4074 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4075 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4076 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4079 $sql .=
" AND f.fk_soc = $socid";
4081 $sql .= $morefilter;
4082 $sql .=
" GROUP BY date_format(f.datef,'%Y%m')";
4083 $sql .=
" ORDER BY date_format(f.datef,'%Y%m') DESC";
4085 return $this->
_get_stats($sql, $mode, $year);
4100 public function get_nb_achat($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4106 $sql =
"SELECT sum(d.qty) as qty, date_format(f.datef, '%Y%m')";
4107 if ($mode ==
'bynumber') {
4108 $sql .=
", count(DISTINCT f.rowid)";
4110 $sql .=
", sum(d.total_ht) as total_ht";
4111 $sql .=
" FROM ".$this->db->prefix().
"facture_fourn_det as d, ".$this->db->prefix().
"facture_fourn as f, ".$this->db->prefix().
"societe as s";
4112 if ($filteronproducttype >= 0) {
4113 $sql .=
", ".$this->db->prefix().
"product as p";
4115 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4116 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4118 $sql .=
" WHERE f.rowid = d.fk_facture_fourn";
4119 if ($this->
id > 0) {
4120 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4122 $sql .=
" AND d.fk_product > 0";
4124 if ($filteronproducttype >= 0) {
4125 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4127 $sql .=
" AND f.fk_soc = s.rowid";
4128 $sql .=
" AND f.entity IN (".getEntity(
'facture_fourn').
")";
4129 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4130 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4133 $sql .=
" AND f.fk_soc = $socid";
4135 $sql .= $morefilter;
4136 $sql .=
" GROUP BY date_format(f.datef,'%Y%m')";
4137 $sql .=
" ORDER BY date_format(f.datef,'%Y%m') DESC";
4139 return $this->
_get_stats($sql, $mode, $year);
4153 public function get_nb_propal($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4156 global $conf, $user;
4158 $sql =
"SELECT sum(d.qty) as qty, date_format(p.datep, '%Y%m')";
4159 if ($mode ==
'bynumber') {
4160 $sql .=
", count(DISTINCT p.rowid)";
4162 $sql .=
", sum(d.total_ht) as total_ht";
4163 $sql .=
" FROM ".$this->db->prefix().
"propaldet as d, ".$this->db->prefix().
"propal as p, ".$this->db->prefix().
"societe as s";
4164 if ($filteronproducttype >= 0) {
4165 $sql .=
", ".$this->db->prefix().
"product as prod";
4167 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4168 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4170 $sql .=
" WHERE p.rowid = d.fk_propal";
4171 if ($this->
id > 0) {
4172 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4174 $sql .=
" AND d.fk_product > 0";
4176 if ($filteronproducttype >= 0) {
4177 $sql .=
" AND prod.rowid = d.fk_product AND prod.fk_product_type = ".((int) $filteronproducttype);
4179 $sql .=
" AND p.fk_soc = s.rowid";
4180 $sql .=
" AND p.entity IN (".getEntity(
'propal').
")";
4181 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4182 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4185 $sql .=
" AND p.fk_soc = ".((int) $socid);
4187 $sql .= $morefilter;
4188 $sql .=
" GROUP BY date_format(p.datep,'%Y%m')";
4189 $sql .=
" ORDER BY date_format(p.datep,'%Y%m') DESC";
4191 return $this->
_get_stats($sql, $mode, $year);
4211 $sql =
"SELECT sum(d.qty) as qty, date_format(p.date_valid, '%Y%m')";
4212 if ($mode ==
'bynumber') {
4213 $sql .=
", count(DISTINCT p.rowid)";
4215 $sql .=
", sum(d.total_ht) as total_ht";
4216 $sql .=
" FROM ".$this->db->prefix().
"supplier_proposaldet as d, ".$this->db->prefix().
"supplier_proposal as p, ".$this->db->prefix().
"societe as s";
4217 if ($filteronproducttype >= 0) {
4218 $sql .=
", ".$this->db->prefix().
"product as prod";
4220 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4221 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4223 $sql .=
" WHERE p.rowid = d.fk_supplier_proposal";
4224 if ($this->
id > 0) {
4225 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4227 $sql .=
" AND d.fk_product > 0";
4229 if ($filteronproducttype >= 0) {
4230 $sql .=
" AND prod.rowid = d.fk_product AND prod.fk_product_type = ".((int) $filteronproducttype);
4232 $sql .=
" AND p.fk_soc = s.rowid";
4233 $sql .=
" AND p.entity IN (".getEntity(
'supplier_proposal').
")";
4234 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4235 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4238 $sql .=
" AND p.fk_soc = ".((int) $socid);
4240 $sql .= $morefilter;
4241 $sql .=
" GROUP BY date_format(p.date_valid,'%Y%m')";
4242 $sql .=
" ORDER BY date_format(p.date_valid,'%Y%m') DESC";
4244 return $this->
_get_stats($sql, $mode, $year);
4258 public function get_nb_order($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4261 global $conf, $user;
4263 $sql =
"SELECT sum(d.qty) as qty, date_format(c.date_commande, '%Y%m')";
4264 if ($mode ==
'bynumber') {
4265 $sql .=
", count(DISTINCT c.rowid)";
4267 $sql .=
", sum(d.total_ht) as total_ht";
4268 $sql .=
" FROM ".$this->db->prefix().
"commandedet as d, ".$this->db->prefix().
"commande as c, ".$this->db->prefix().
"societe as s";
4269 if ($filteronproducttype >= 0) {
4270 $sql .=
", ".$this->db->prefix().
"product as p";
4272 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4273 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4275 $sql .=
" WHERE c.rowid = d.fk_commande";
4276 if ($this->
id > 0) {
4277 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4279 $sql .=
" AND d.fk_product > 0";
4281 if ($filteronproducttype >= 0) {
4282 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4284 $sql .=
" AND c.fk_soc = s.rowid";
4285 $sql .=
" AND c.entity IN (".getEntity(
'commande').
")";
4286 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4287 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4290 $sql .=
" AND c.fk_soc = ".((int) $socid);
4292 $sql .= $morefilter;
4293 $sql .=
" GROUP BY date_format(c.date_commande,'%Y%m')";
4294 $sql .=
" ORDER BY date_format(c.date_commande,'%Y%m') DESC";
4296 return $this->
_get_stats($sql, $mode, $year);
4313 global $conf, $user;
4315 $sql =
"SELECT sum(d.qty) as qty, date_format(c.date_commande, '%Y%m')";
4316 if ($mode ==
'bynumber') {
4317 $sql .=
", count(DISTINCT c.rowid)";
4319 $sql .=
", sum(d.total_ht) as total_ht";
4320 $sql .=
" FROM ".$this->db->prefix().
"commande_fournisseurdet as d, ".$this->db->prefix().
"commande_fournisseur as c, ".$this->db->prefix().
"societe as s";
4321 if ($filteronproducttype >= 0) {
4322 $sql .=
", ".$this->db->prefix().
"product as p";
4324 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4325 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4327 $sql .=
" WHERE c.rowid = d.fk_commande";
4328 if ($this->
id > 0) {
4329 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4331 $sql .=
" AND d.fk_product > 0";
4333 if ($filteronproducttype >= 0) {
4334 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4336 $sql .=
" AND c.fk_soc = s.rowid";
4337 $sql .=
" AND c.entity IN (".getEntity(
'supplier_order').
")";
4338 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4339 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4342 $sql .=
" AND c.fk_soc = ".((int) $socid);
4344 $sql .= $morefilter;
4345 $sql .=
" GROUP BY date_format(c.date_commande,'%Y%m')";
4346 $sql .=
" ORDER BY date_format(c.date_commande,'%Y%m') DESC";
4348 return $this->
_get_stats($sql, $mode, $year);
4362 public function get_nb_contract($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4365 global $conf, $user;
4367 $sql =
"SELECT sum(d.qty) as qty, date_format(c.date_contrat, '%Y%m')";
4368 if ($mode ==
'bynumber') {
4369 $sql .=
", count(DISTINCT c.rowid)";
4371 $sql .=
", sum(d.total_ht) as total_ht";
4372 $sql .=
" FROM ".$this->db->prefix().
"contratdet as d, ".$this->db->prefix().
"contrat as c, ".$this->db->prefix().
"societe as s";
4373 if ($filteronproducttype >= 0) {
4374 $sql .=
", ".$this->db->prefix().
"product as p";
4376 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4377 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4379 $sql .=
" WHERE c.entity IN (".getEntity(
'contract').
")";
4380 $sql .=
" AND c.rowid = d.fk_contrat";
4382 if ($this->
id > 0) {
4383 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4385 $sql .=
" AND d.fk_product > 0";
4387 if ($filteronproducttype >= 0) {
4388 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4390 $sql .=
" AND c.fk_soc = s.rowid";
4392 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4393 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4396 $sql .=
" AND c.fk_soc = ".((int) $socid);
4398 $sql .= $morefilter;
4399 $sql .=
" GROUP BY date_format(c.date_contrat,'%Y%m')";
4400 $sql .=
" ORDER BY date_format(c.date_contrat,'%Y%m') DESC";
4402 return $this->
_get_stats($sql, $mode, $year);
4416 public function get_nb_mos($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4419 global $conf, $user;
4421 $sql =
"SELECT sum(d.qty), date_format(d.date_valid, '%Y%m')";
4422 if ($mode ==
'bynumber') {
4423 $sql .=
", count(DISTINCT d.rowid)";
4425 $sql .=
" FROM ".$this->db->prefix().
"mrp_mo as d LEFT JOIN ".$this->db->prefix().
"societe as s ON d.fk_soc = s.rowid";
4426 if ($filteronproducttype >= 0) {
4427 $sql .=
", ".$this->db->prefix().
"product as p";
4429 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4430 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4433 $sql .=
" WHERE d.entity IN (".getEntity(
'mo').
")";
4434 $sql .=
" AND d.status > 0";
4436 if ($this->
id > 0) {
4437 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4439 $sql .=
" AND d.fk_product > 0";
4441 if ($filteronproducttype >= 0) {
4442 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4445 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4446 $sql .=
" AND d.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4449 $sql .=
" AND d.fk_soc = ".((int) $socid);
4451 $sql .= $morefilter;
4452 $sql .=
" GROUP BY date_format(d.date_valid,'%Y%m')";
4453 $sql .=
" ORDER BY date_format(d.date_valid,'%Y%m') DESC";
4455 return $this->
_get_stats($sql, $mode, $year);
4475 if (!is_numeric($id_pere)) {
4478 if (!is_numeric($id_fils)) {
4481 if (!is_numeric($incdec)) {
4491 $sql =
"SELECT fk_product_pere from ".$this->db->prefix().
"product_association";
4492 $sql .=
" WHERE fk_product_pere = ".((int) $id_fils).
" AND fk_product_fils = ".((int) $id_pere);
4493 if (!$this->db->query($sql)) {
4498 $sql =
"SELECT MAX(rang) as max_rank FROM ".$this->db->prefix().
"product_association";
4499 $sql .=
" WHERE fk_product_pere = ".((int) $id_pere);
4500 $resql = $this->db->query($sql);
4502 $obj = $this->db->fetch_object($resql);
4503 $rank = $obj->max_rank + 1;
4505 $sql =
"INSERT INTO ".$this->db->prefix().
"product_association(fk_product_pere,fk_product_fils,qty,incdec,rang)";
4506 $sql .=
" VALUES (".((int) $id_pere).
", ".((int) $id_fils).
", ".
price2num($qty,
'MS').
", ".
price2num($incdec,
'MS').
", ".((int) $rank).
")";
4507 if (! $this->db->query($sql)) {
4513 $result = $this->
call_trigger(
'PRODUCT_SUBPRODUCT_ADD', $user);
4515 $this->error = $this->db->lasterror();
4516 dol_syslog(get_class($this).
'::addSubproduct error='.$this->error, LOG_ERR);
4548 if (!is_numeric($id_pere)) {
4551 if (!is_numeric($id_fils)) {
4554 if (!is_numeric($incdec)) {
4557 if (!is_numeric($qty)) {
4561 $sql =
'UPDATE '.$this->db->prefix().
'product_association SET ';
4562 $sql .=
'qty = '.price2num($qty,
'MS');
4563 $sql .=
',incdec = '.price2num($incdec,
'MS');
4564 $sql .=
' WHERE fk_product_pere = '.((int) $id_pere).
' AND fk_product_fils = '.((int) $id_fils);
4566 if (!$this->db->query($sql)) {
4572 $result = $this->
call_trigger(
'PRODUCT_SUBPRODUCT_UPDATE', $user);
4574 $this->error = $this->db->lasterror();
4575 dol_syslog(get_class($this).
'::updateSubproduct error='.$this->error, LOG_ERR);
4599 if (!is_numeric($fk_parent)) {
4602 if (!is_numeric($fk_child)) {
4606 $sql =
"DELETE FROM ".$this->db->prefix().
"product_association";
4607 $sql .=
" WHERE fk_product_pere = ".((int) $fk_parent);
4608 $sql .=
" AND fk_product_fils = ".((int) $fk_child);
4610 dol_syslog(get_class($this).
'::del_sousproduit', LOG_DEBUG);
4611 if (!$this->db->query($sql)) {
4617 $sqlrank =
"SELECT rowid, rang FROM ".$this->db->prefix().
"product_association";
4618 $sqlrank .=
" WHERE fk_product_pere = ".((int) $fk_parent);
4619 $sqlrank .=
" ORDER BY rang";
4620 $resqlrank = $this->db->query($sqlrank);
4623 while ($objrank = $this->db->fetch_object($resqlrank)) {
4625 $sql =
"UPDATE ".$this->db->prefix().
"product_association";
4626 $sql .=
" SET rang = ".((int) $cpt);
4627 $sql .=
" WHERE rowid = ".((int) $objrank->rowid);
4628 if (! $this->db->query($sql)) {
4637 $result = $this->
call_trigger(
'PRODUCT_SUBPRODUCT_DELETE', $user);
4639 $this->error = $this->db->lasterror();
4640 dol_syslog(get_class($this).
'::delSubproduct error='.$this->error, LOG_ERR);
4660 $sql =
"SELECT fk_product_pere, qty, incdec";
4661 $sql .=
" FROM ".$this->db->prefix().
"product_association";
4662 $sql .=
" WHERE fk_product_pere = ".((int) $fk_parent);
4663 $sql .=
" AND fk_product_fils = ".((int) $fk_child);
4665 $result = $this->db->query($sql);
4667 $num = $this->db->num_rows($result);
4670 $obj = $this->db->fetch_object($result);
4672 $this->is_sousproduit_qty = $obj->qty;
4673 $this->is_sousproduit_incdec = $obj->incdec;
4704 dol_syslog(get_class($this).
"::add_fournisseur id_fourn = ".$id_fourn.
" ref_fourn=".
$ref_fourn.
" quantity=".$quantity, LOG_DEBUG);
4711 $sql =
"SELECT rowid, fk_product";
4712 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price";
4713 $sql .=
" WHERE fk_soc = ".((int) $id_fourn);
4714 $sql .=
" AND ref_fourn = '".$this->db->escape(
$ref_fourn).
"'";
4715 $sql .=
" AND fk_product <> ".((int) $this->
id);
4716 $sql .=
" AND entity IN (".getEntity(
'productsupplierprice').
")";
4718 $resql = $this->db->query($sql);
4720 $obj = $this->db->fetch_object($resql);
4723 $this->product_id_already_linked = $obj->fk_product;
4726 $this->db->free($resql);
4730 $sql =
"SELECT rowid";
4731 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price";
4732 $sql .=
" WHERE fk_soc = ".((int) $id_fourn);
4734 $sql .=
" AND ref_fourn = '".$this->db->escape(
$ref_fourn).
"'";
4736 $sql .=
" AND (ref_fourn = '' OR ref_fourn IS NULL)";
4738 $sql .=
" AND quantity = ".((float) $quantity);
4739 $sql .=
" AND fk_product = ".((int) $this->
id);
4740 $sql .=
" AND entity IN (".getEntity(
'productsupplierprice').
")";
4742 $resql = $this->db->query($sql);
4744 $obj = $this->db->fetch_object($resql);
4748 $sql =
"INSERT INTO ".$this->db->prefix().
"product_fournisseur_price(";
4751 $sql .=
", fk_product";
4753 $sql .=
", ref_fourn";
4754 $sql .=
", quantity";
4755 $sql .=
", fk_user";
4757 $sql .=
") VALUES (";
4758 $sql .=
"'".$this->db->idate($now).
"'";
4759 $sql .=
", ".((int) $conf->entity);
4760 $sql .=
", ".((int) $this->
id);
4761 $sql .=
", ".((int) $id_fourn);
4762 $sql .=
", '".$this->db->escape(
$ref_fourn).
"'";
4763 $sql .=
", ".((float) $quantity);
4764 $sql .=
", ".((int) $user->id);
4768 if ($this->db->query($sql)) {
4769 $this->product_fourn_price_id = $this->db->last_insert_id($this->db->prefix().
"product_fournisseur_price");
4772 $this->error = $this->db->lasterror();
4777 $this->product_fourn_price_id = $obj->rowid;
4781 $this->error = $this->db->lasterror();
4800 $sql =
"SELECT DISTINCT p.fk_soc";
4801 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price as p";
4802 $sql .=
" WHERE p.fk_product = ".((int) $this->
id);
4803 $sql .=
" AND p.entity = ".((int) $conf->entity);
4805 $result = $this->db->query($sql);
4807 $num = $this->db->num_rows($result);
4810 $obj = $this->db->fetch_object($result);
4811 $list[$i] = $obj->fk_soc;
4829 global $conf, $user;
4836 $sql =
"INSERT INTO ".$this->db->prefix().
"product_price (";
4838 $sql .=
", fk_product";
4839 $sql .=
", date_price";
4840 $sql .=
", price_level";
4842 $sql .=
", price_ttc";
4843 $sql .=
", price_min";
4844 $sql .=
", price_min_ttc";
4845 $sql .=
", price_base_type";
4846 $sql .=
", price_label";
4847 $sql .=
", default_vat_code";
4849 $sql .=
", recuperableonly";
4850 $sql .=
", localtax1_tx";
4851 $sql .=
", localtax1_type";
4852 $sql .=
", localtax2_tx";
4853 $sql .=
", localtax2_type";
4854 $sql .=
", fk_user_author";
4856 $sql .=
", price_by_qty";
4857 $sql .=
", fk_price_expression";
4858 $sql .=
", fk_multicurrency";
4859 $sql .=
", multicurrency_code";
4860 $sql .=
", multicurrency_tx";
4861 $sql .=
", multicurrency_price";
4862 $sql .=
", multicurrency_price_ttc";
4867 $sql .=
", '".$this->db->idate($now).
"'";
4868 $sql .=
", price_level";
4870 $sql .=
", price_ttc";
4871 $sql .=
", price_min";
4872 $sql .=
", price_min_ttc";
4873 $sql .=
", price_base_type";
4874 $sql .=
", price_label";
4875 $sql .=
", default_vat_code";
4877 $sql .=
", recuperableonly";
4878 $sql .=
", localtax1_tx";
4879 $sql .=
", localtax1_type";
4880 $sql .=
", localtax2_tx";
4881 $sql .=
", localtax2_type";
4882 $sql .=
", ".$user->id;
4884 $sql .=
", price_by_qty";
4885 $sql .=
", fk_price_expression";
4886 $sql .=
", fk_multicurrency";
4887 $sql .=
", multicurrency_code";
4888 $sql .=
", multicurrency_tx";
4889 $sql .=
", multicurrency_price";
4890 $sql .=
", multicurrency_price_ttc";
4891 $sql .=
" FROM ".$this->db->prefix().
"product_price ps";
4892 $sql .=
" WHERE fk_product = ".((int) $fromId);
4893 $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)";
4894 $sql .=
" ORDER BY date_price DESC";
4897 $resql = $this->db->query($sql);
4899 $this->db->rollback();
4903 $this->db->commit();
4920 $sql =
'INSERT INTO '.$this->db->prefix().
'product_association (fk_product_pere, fk_product_fils, qty, incdec)';
4921 $sql .=
" SELECT ".$toId.
", fk_product_fils, qty, incdec FROM ".$this->db->prefix().
"product_association";
4922 $sql .=
" WHERE fk_product_pere = ".((int) $fromId);
4924 dol_syslog(get_class($this).
'::clone_association', LOG_DEBUG);
4925 if (!$this->db->query($sql)) {
4926 $this->db->rollback();
4930 $this->db->commit();
4963 $sql =
"INSERT ".$this->db->prefix().
"product_fournisseur_price (";
4964 $sql .=
" datec, fk_product, fk_soc, price, quantity, fk_user, tva_tx)";
4965 $sql .=
" SELECT '".$this->db->idate($now).
"', ".((int) $toId).
", fk_soc, price, quantity, fk_user, tva_tx";
4966 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price";
4967 $sql .=
" WHERE fk_product = ".((int) $fromId);
4969 dol_syslog(get_class($this).
'::clone_fournisseurs', LOG_DEBUG);
4970 $resql = $this->db->query($sql);
4972 $this->db->rollback();
4975 $this->db->commit();
4993 public function fetch_prod_arbo($prod, $compl_path =
'', $multiply = 1, $level = 1, $id_parent = 0, $ignore_stock_load = 0)
4996 global $conf, $langs;
5000 foreach ($prod as $id_product => $desc_pere) {
5001 if (is_array($desc_pere)) {
5002 $id = (!empty($desc_pere[0]) ? $desc_pere[0] :
'');
5003 $nb = (!empty($desc_pere[1]) ? $desc_pere[1] :
'');
5004 $type = (!empty($desc_pere[2]) ? $desc_pere[2] :
'');
5005 $label = (!empty($desc_pere[3]) ? $desc_pere[3] :
'');
5006 $incdec = (!empty($desc_pere[4]) ? $desc_pere[4] : 0);
5008 if ($multiply < 1) {
5013 if (is_null($tmpproduct)) {
5014 $tmpproduct =
new Product($this->db);
5016 $tmpproduct->fetch($id);
5018 if (empty($ignore_stock_load) && ($tmpproduct->isProduct() ||
getDolGlobalString(
'STOCK_SUPPORTS_SERVICES'))) {
5019 $tmpproduct->load_stock(
'nobatch,novirtual');
5022 $this->res[] = array(
5024 'id_parent' => $id_parent,
5025 'ref' => $tmpproduct->ref,
5027 'nb_total' => $nb * $multiply,
5028 'stock' => $tmpproduct->stock_reel,
5029 'stock_alert' => $tmpproduct->seuil_stock_alerte,
5031 'fullpath' => $compl_path.$label,
5033 'desiredstock' => $tmpproduct->desiredstock,
5035 'incdec' => $incdec,
5036 'entity' => $tmpproduct->entity
5040 if (isset($desc_pere[
'childs']) && is_array($desc_pere[
'childs'])) {
5042 $this->
fetch_prod_arbo($desc_pere[
'childs'], $compl_path.$desc_pere[3].
" -> ", $desc_pere[1] * $multiply, $level + 1, $id, $ignore_stock_load);
5060 $this->res = array();
5061 if (isset($this->sousprods) && is_array($this->sousprods)) {
5062 foreach ($this->sousprods as $prod_name => $desc_product) {
5063 if (is_array($desc_product)) {
5064 $this->
fetch_prod_arbo($desc_product,
"", $multiply, 1, $this->
id, $ignore_stock_load);
5083 $sql =
"SELECT COUNT(pa.rowid) as nb";
5084 $sql .=
" FROM ".$this->db->prefix().
"product_association as pa";
5086 $sql .=
" WHERE pa.fk_product_fils = ".((int) $this->
id).
" OR pa.fk_product_pere = ".((int) $this->
id);
5087 } elseif ($mode == -1) {
5088 $sql .=
" WHERE pa.fk_product_fils = ".((int) $this->
id);
5089 } elseif ($mode == 1) {
5090 $sql .=
" WHERE pa.fk_product_pere = ".((int) $this->
id);
5093 $resql = $this->db->query($sql);
5095 $obj = $this->db->fetch_object($resql);
5114 $sql =
"SELECT count(rowid) as nb FROM ".$this->db->prefix().
"product_attribute_combination WHERE fk_product_parent = ".((int) $this->
id);
5115 $sql .=
" AND entity IN (".getEntity(
'product').
")";
5117 $resql = $this->db->query($sql);
5119 $obj = $this->db->fetch_object($resql);
5137 if (isModEnabled(
'variants')) {
5138 $sql =
"SELECT rowid FROM ".$this->db->prefix().
"product_attribute_combination WHERE fk_product_child = ".((int) $this->
id).
" AND entity IN (".
getEntity(
'product').
")";
5140 $query = $this->db->query($sql);
5143 if (!$this->db->num_rows($query)) {
5164 $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";
5165 $sql .=
", p.tosell as status, p.tobuy as status_buy";
5166 $sql .=
" FROM ".$this->db->prefix().
"product_association as pa,";
5167 $sql .=
" ".$this->db->prefix().
"product as p";
5168 $sql .=
" WHERE p.rowid = pa.fk_product_pere";
5169 $sql .=
" AND pa.fk_product_fils = ".((int) $this->
id);
5171 $res = $this->db->query($sql);
5174 while ($record = $this->db->fetch_array($res)) {
5176 $prods[$record[
'id']][
'id'] = $record[
'rowid'];
5177 $prods[$record[
'id']][
'ref'] = $record[
'ref'];
5178 $prods[$record[
'id']][
'label'] = $record[
'label'];
5179 $prods[$record[
'id']][
'qty'] = $record[
'qty'];
5180 $prods[$record[
'id']][
'incdec'] = $record[
'incdec'];
5181 $prods[$record[
'id']][
'fk_product_type'] = $record[
'fk_product_type'];
5182 $prods[$record[
'id']][
'entity'] = $record[
'entity'];
5183 $prods[$record[
'id']][
'status'] = $record[
'status'];
5184 $prods[$record[
'id']][
'status_buy'] = $record[
'status_buy'];
5203 public function getChildsArbo($id, $firstlevelonly = 0, $level = 1, $parents = array())
5209 $sql =
"SELECT p.rowid, p.ref, p.label as label, p.fk_product_type,";
5210 $sql .=
" pa.qty as qty, pa.fk_product_fils as id, pa.incdec,";
5211 $sql .=
" pa.rowid as fk_association, pa.rang";
5212 $sql .=
" FROM ".$this->db->prefix().
"product as p,";
5213 $sql .=
" ".$this->db->prefix().
"product_association as pa";
5214 $sql .=
" WHERE p.rowid = pa.fk_product_fils";
5215 $sql .=
" AND pa.fk_product_pere = ".((int) $id);
5216 $sql .=
" AND pa.fk_product_fils <> ".((int) $id);
5217 $sql .=
" ORDER BY pa.rang";
5219 dol_syslog(get_class($this).
'::getChildsArbo id='.$id.
' level='.$level.
' parents='.(is_array($parents) ? implode(
',', $parents) : $parents), LOG_DEBUG);
5226 $res = $this->db->query($sql);
5229 if ($this->db->num_rows($res) > 0) {
5233 while ($rec = $this->db->fetch_array($res)) {
5234 if (in_array($rec[
'id'], $parents)) {
5235 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);
5239 $prods[$rec[
'rowid']] = array(
5242 2 => $rec[
'fk_product_type'],
5243 3 => $this->db->escape($rec[
'label']),
5244 4 => $rec[
'incdec'],
5246 6 => $rec[
'fk_association'],
5251 if (empty($firstlevelonly)) {
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)) {
5391 if (!empty($this->pmp) && $this->pmp) {
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 $weBillOrderOrShipmentReception =
getDolGlobalString(
'STOCK_DO_WE_BILL_ORDER_OR_SHIPMENTECEPTION_FOR_VIRTUALSTOCK',
'order');
5995 $this->stock_theorique -= ($stock_commande_client - $stock_sending_client);
5999 $result = $tmpnewprod->load_stats_commande(0,
'0', 1);
6000 $this->stock_theorique += $tmpnewprod->stats_commande[
'qty'];
6002 } elseif (
getDolGlobalString(
'STOCK_CALCULATE_ON_BILL') && $weBillOrderOrShipmentReception ==
'order') {
6003 $this->stock_theorique -= $stock_commande_client;
6004 } elseif (
getDolGlobalString(
'STOCK_CALCULATE_ON_BILL') && $weBillOrderOrShipmentReception ==
'shipmentreception') {
6005 $this->stock_theorique -= ($stock_commande_client - $stock_sending_client);
6010 $this->stock_theorique += ($stock_commande_fournisseur - $stock_reception_fournisseur);
6012 $this->stock_theorique += ($stock_commande_fournisseur - $stock_reception_fournisseur);
6014 if (
getDolGlobalString(
'STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER_INCLUDE_DRAFT')) {
6016 $result = $tmpnewprod->load_stats_commande_fournisseur(0,
'0', 1);
6017 $this->stock_theorique += $this->stats_commande_fournisseur[
'qty'];
6019 $this->stock_theorique -= $stock_reception_fournisseur;
6020 } elseif (
getDolGlobalString(
'STOCK_CALCULATE_ON_SUPPLIER_BILL') && $weBillOrderOrShipmentReception ==
'order') {
6021 $this->stock_theorique += $stock_commande_fournisseur;
6022 } elseif (
getDolGlobalString(
'STOCK_CALCULATE_ON_SUPPLIER_BILL') && $weBillOrderOrShipmentReception ==
'shipmentreception') {
6023 $this->stock_theorique += ($stock_commande_fournisseur - $stock_reception_fournisseur);
6026 $parameters = array(
'id' => $this->
id,
'includedraftpoforvirtual' => $includedraftpoforvirtual);
6028 $reshook = $hookmanager->executeHooks(
'loadvirtualstock', $parameters, $this, $action);
6030 $this->stock_theorique = $hookmanager->resArray[
'stock_theorique'];
6031 } elseif ($reshook == 0 && isset($hookmanager->resArray[
'stock_stats_hook'])) {
6032 $this->stock_theorique += $hookmanager->resArray[
'stock_stats_hook'];
6036 if (!empty($this->stock_warehouse) &&
getDolGlobalString(
'STOCK_ALLOW_VIRTUAL_STOCK_PER_WAREHOUSE')) {
6037 foreach ($this->stock_warehouse as $warehouseid => $stockwarehouse) {
6038 if (isModEnabled(
'mrp')) {
6045 if ($this->fk_default_warehouse == $warehouseid) {
6046 $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']);
6048 $this->stock_warehouse[$warehouseid]->virtual = $this->stock_warehouse[$warehouseid]->real + $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'];
6068 $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";
6069 $sql .=
" WHERE pb.fk_product_stock = ps.rowid AND ps.fk_product = ".((int) $this->
id).
" AND pb.batch = '".$this->db->escape($batch).
"'";
6070 $sql .=
" GROUP BY pb.batch, pb.eatby, pb.sellby";
6071 dol_syslog(get_class($this).
"::loadBatchInfo load first entry found for lot/serial = ".$batch, LOG_DEBUG);
6072 $resql = $this->db->query($sql);
6074 $num = $this->db->num_rows($resql);
6077 $obj = $this->db->fetch_object($resql);
6078 $result[] = array(
'batch' => $batch,
'eatby' => $this->db->jdate($obj->eatby),
'sellby' => $this->db->jdate($obj->sellby),
'qty' => $obj->qty);
6084 $this->db->rollback();
6102 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6108 $dir .=
'/'.get_exdir($this->
id, 2, 0, 0, $this,
'product').$this->id.
"/photos";
6110 $dir .=
'/'.get_exdir(0, 0, 0, 0, $this,
'product').dol_sanitizeFileName($this->
ref);
6115 $dir_osencoded = $dir;
6117 if (is_dir($dir_osencoded)) {
6118 $originImage = $dir.
'/'.$file[
'name'];
6129 if (is_numeric($result) && $result > 0) {
6146 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6147 include_once DOL_DOCUMENT_ROOT.
'/core/lib/images.lib.php';
6153 $dir .=
'/'.get_exdir($this->
id, 2, 0, 0, $this,
'product').$this->id.
"/photos/";
6155 $dir .=
'/'.get_exdir(0, 0, 0, 0, $this,
'product');
6161 if (file_exists($dir_osencoded)) {
6162 $handle = opendir($dir_osencoded);
6163 if (is_resource($handle)) {
6164 while (($file = readdir($handle)) !==
false) {
6166 $file = mb_convert_encoding($file,
'UTF-8',
'ISO-8859-1');
6188 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6189 include_once DOL_DOCUMENT_ROOT.
'/core/lib/images.lib.php';
6195 $handle = @opendir($dir_osencoded);
6196 if (is_resource($handle)) {
6197 while (($file = readdir($handle)) !==
false) {
6199 $file = mb_convert_encoding($file,
'UTF-8',
'ISO-8859-1');
6206 $photo_vignette =
'';
6208 if (preg_match(
'/('.$this->regeximgext.
')$/i', $photo, $regs)) {
6209 $photo_vignette = preg_replace(
'/'.$regs[0].
'/i',
'', $photo).
'_small'.$regs[0];
6212 $dirthumb = $dir.
'thumbs/';
6216 $obj[
'photo'] = $photo;
6217 if ($photo_vignette &&
dol_is_file($dirthumb.$photo_vignette)) {
6218 $obj[
'photo_vignette'] =
'thumbs/'.$photo_vignette;
6220 $obj[
'photo_vignette'] =
"";
6223 $tabobj[$nbphoto - 1] = $obj;
6226 if ($nbmax && $nbphoto >= $nbmax) {
6248 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6249 include_once DOL_DOCUMENT_ROOT.
'/core/lib/images.lib.php';
6251 $dir = dirname($file).
'/';
6252 $dirthumb = $dir.
'/thumbs/';
6253 $filename = preg_replace(
'/'.preg_quote($dir,
'/').
'/i',
'', $file);
6259 if (preg_match(
'/('.$this->regeximgext.
')$/i', $filename, $regs)) {
6260 $photo_vignette = preg_replace(
'/'.$regs[0].
'/i',
'', $filename).
'_small'.$regs[0];
6261 if (file_exists(
dol_osencode($dirthumb.$photo_vignette))) {
6265 $photo_vignette = preg_replace(
'/'.$regs[0].
'/i',
'', $filename).
'_mini'.$regs[0];
6266 if (file_exists(
dol_osencode($dirthumb.$photo_vignette))) {
6283 $infoImg = getimagesize($file_osencoded);
6284 $this->imgWidth = $infoImg[0];
6285 $this->imgHeight = $infoImg[1];
6295 global $hookmanager;
6297 $this->nb = array();
6299 $sql =
"SELECT count(p.rowid) as nb, fk_product_type";
6300 $sql .=
" FROM ".$this->db->prefix().
"product as p";
6301 $sql .=
' WHERE p.entity IN ('.getEntity($this->element, 1).
')';
6303 if (is_object($hookmanager)) {
6304 $parameters = array();
6305 $reshook = $hookmanager->executeHooks(
'printFieldListWhere', $parameters, $this);
6306 $sql .= $hookmanager->resPrint;
6308 $sql .=
' GROUP BY fk_product_type';
6310 $resql = $this->db->query($sql);
6312 while ($obj = $this->db->fetch_object($resql)) {
6313 if ($obj->fk_product_type == 1) {
6314 $this->nb[
"services"] = $obj->nb;
6316 $this->nb[
"products"] = $obj->nb;
6319 $this->db->free($resql);
6323 $this->error = $this->db->error();
6365 return ($this->mandatory_period == 1 ?
true :
false);
6375 return ($this->status_batch > 0 ?
true :
false);
6395 $dirsociete = array_merge(array(
'/core/modules/barcode/'), $conf->modules_parts[
'barcode']);
6396 foreach ($dirsociete as $dirroot) {
6404 '@phan-var-force ModeleNumRefBarCode $module';
6406 $result = $mod->getNextValue(
$object, $type);
6408 dol_syslog(get_class($this).
"::get_barcode barcode=".$result.
" module=".$var);
6425 $this->specimen = 1;
6427 $this->
ref =
'PRODUCT_SPEC';
6428 $this->label =
'PRODUCT SPECIMEN';
6429 $this->
description =
'This is description of this product specimen that was created the '.dol_print_date($now,
'dayhourlog').
'.';
6430 $this->specimen = 1;
6431 $this->country_id = 1;
6433 $this->status_buy = 1;
6435 $this->sell_or_eat_by_mandatory = 0;
6436 $this->note_private =
'This is a comment (private)';
6437 $this->note_public =
'This is a comment (public)';
6438 $this->date_creation = $now;
6439 $this->date_modification = $now;
6442 $this->weight_units = 3;
6445 $this->length_units = 1;
6447 $this->width_units = 0;
6448 $this->height =
null;
6449 $this->height_units =
null;
6451 $this->surface = 30;
6452 $this->surface_units = 0;
6453 $this->volume = 300;
6454 $this->volume_units = 0;
6456 $this->barcode = -1;
6471 if (!$this->fk_unit) {
6475 $langs->load(
'products');
6477 $label_type =
'label';
6478 if ($type ==
'short') {
6479 $label_type =
'short_label';
6482 $sql =
"SELECT ".$label_type.
", code from ".$this->db->prefix().
"c_units where rowid = ".((int) $this->fk_unit);
6484 $resql = $this->db->query($sql);
6486 $this->error = $this->db->error();
6487 dol_syslog(get_class($this).
"::getLabelOfUnit Error ".$this->error, LOG_ERR);
6489 } elseif ($this->db->num_rows($resql) > 0 && $res = $this->db->fetch_array($resql)) {
6490 $label = ($label_type ==
'short_label' ? $res[$label_type] :
'unit'.$res[
'code']);
6492 $this->db->free($resql);
6508 $maxpricesupplier = 0;
6511 include_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
6513 $product_fourn_list = $product_fourn->list_product_fournisseur_price($this->
id,
'',
'');
6515 if (is_array($product_fourn_list) && count($product_fourn_list) > 0) {
6516 foreach ($product_fourn_list as $productfourn) {
6517 if ($productfourn->fourn_unitprice > $maxpricesupplier) {
6518 $maxpricesupplier = $productfourn->fourn_unitprice;
6522 $maxpricesupplier *= $conf->global->PRODUCT_MINIMUM_RECOMMENDED_PRICE;
6526 return $maxpricesupplier;
6542 require_once DOL_DOCUMENT_ROOT.
'/categories/class/categorie.class.php';
6543 return parent::setCategoriesCommon($categories, Categorie::TYPE_PRODUCT);
6557 'product_customer_price',
6558 'product_customer_price_log'
6579 $sql =
"SELECT rowid, level, fk_level, var_percent, var_min_percent FROM ".$this->db->prefix().
"product_pricerules";
6580 $query = $this->db->query($sql);
6584 while ($result = $this->db->fetch_object($query)) {
6585 $rules[$result->level] = $result;
6594 for ($i = 1; $i <= $nbofproducts; $i++) {
6595 $price = $baseprice;
6596 $price_min = $baseprice;
6600 if ($i > 1 && isset($rules[$i]->var_percent) && $rules[$i]->var_percent) {
6601 $price = $prices[$rules[$i]->fk_level] * (1 + ($rules[$i]->var_percent / 100));
6604 $prices[$i] = $price;
6607 if (isset($rules[$i]->var_min_percent) && $rules[$i]->var_min_percent) {
6608 $price_min = $price * (1 - ($rules[$i]->var_min_percent / 100));
6612 $check_amount = (($price == $this->multiprices[$i]) && ($price_min == $this->multiprices_min[$i]));
6613 $check_type = ($baseprice == $this->multiprices_base_type[$i]);
6615 if ($check_amount && $check_type) {
6619 if ($this->
updatePrice($price, $price_type, $user, $price_vat, $price_min, $i, $npr, $psq,
true) < 0) {
6637 return $user->rights->produit;
6639 return $user->rights->service;
6651 $sql =
"SELECT p.rowid, p.ref, p.datec as date_creation, p.tms as date_modification,";
6652 $sql .=
" p.fk_user_author, p.fk_user_modif";
6653 $sql .=
" FROM ".$this->db->prefix().$this->table_element.
" as p";
6654 $sql .=
" WHERE p.rowid = ".((int) $id);
6656 $result = $this->db->query($sql);
6658 if ($this->db->num_rows($result)) {
6659 $obj = $this->db->fetch_object($result);
6661 $this->
id = $obj->rowid;
6662 $this->
ref = $obj->ref;
6664 $this->user_creation_id = $obj->fk_user_author;
6665 $this->user_modification_id = $obj->fk_user_modif;
6667 $this->date_creation = $this->db->jdate($obj->date_creation);
6668 $this->date_modification = $this->db->jdate($obj->date_modification);
6671 $this->db->free($result);
6687 if (empty($this->duration_value)) {
6688 $this->errors[] =
'ErrorDurationForServiceNotDefinedCantCalculateHourlyPrice';
6692 if ($this->duration_unit ==
'i') {
6693 $prodDurationHours = 1. / 60;
6695 if ($this->duration_unit ==
'h') {
6696 $prodDurationHours = 1.;
6698 if ($this->duration_unit ==
'd') {
6699 $prodDurationHours = 24.;
6701 if ($this->duration_unit ==
'w') {
6702 $prodDurationHours = 24. * 7;
6704 if ($this->duration_unit ==
'm') {
6705 $prodDurationHours = 24. * 30;
6707 if ($this->duration_unit ==
'y') {
6708 $prodDurationHours = 24. * 365;
6712 return $prodDurationHours;
6725 global $langs,$conf;
6727 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
6729 $return =
'<div class="box-flex-item box-flex-grow-zero">';
6730 $return .=
'<div class="info-box info-box-sm">';
6731 $return .=
'<div class="info-box-img">';
6734 $label .= $this->
show_photos(
'product', $conf->product->multidir_output[$this->entity], 1, 1, 0, 0, 0, 120, 160, 0, 0, 0,
'',
'photoref photokanban');
6744 $return .=
'</div>';
6745 $return .=
'<div class="info-box-content">';
6746 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this,
'getNomUrl') ? $this->
getNomUrl() : $this->ref).
'</span>';
6747 if ($selected >= 0) {
6748 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
6750 if (property_exists($this,
'label')) {
6751 $return .=
'<br><span class="info-box-label opacitymedium inline-block tdoverflowmax150 valignmiddle" title="'.dol_escape_htmltag($this->label).
'">'.
dol_escape_htmltag($this->label).
'</span>';
6753 if (property_exists($this,
'price') && property_exists($this,
'price_ttc')) {
6754 if ($this->price_base_type ==
'TTC') {
6755 $return .=
'<br><span class="info-box-status amount">'.price($this->price_ttc).
' '.$langs->trans(
"TTC").
'</span>';
6758 $return .=
'<br><span class="info-box-status amount">'.price($this->
price).
' '.$langs->trans(
"HT").
'</span>';
6763 if (property_exists($this,
'stock_reel') && $this->
isProduct()) {
6764 $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>';
6767 if (method_exists($this,
'getLibStatut')) {
6769 $return .=
'<br><div class="info-box-status inline-block valignmiddle">'.$this->getLibStatut(3, 1).
' '.$this->
getLibStatut(3, 0).
'</div>';
6771 $return .=
'<div class="info-box-status inline-block valignmiddle marginleftonly paddingleft">'.$this->getLibStatut(3, 1).
' '.$this->
getLibStatut(3, 0).
'</div>';
6774 $return .=
'</div>';
6775 $return .=
'</div>';
6776 $return .=
'</div>';
6787 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.
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