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' ),
91 'bom_bom' => array(
'name' =>
'BOM'),
92 'bom_bomline' => array(
'name' =>
'BOMLine',
'parent' =>
'bom_bom',
'parentkey' =>
'fk_bom'),
100 public $picto =
'product';
111 public $regeximgext =
'\.gif|\.jpg|\.jpeg|\.png|\.bmp|\.webp|\.xpm|\.xbm';
158 public $price_formated;
170 public $price_ttc_formated;
184 public $price_min_ttc;
190 public $price_base_type;
200 public $multiprices = array();
204 public $multiprices_ttc = array();
208 public $multiprices_base_type = array();
212 public $multiprices_default_vat_code = array();
216 public $multiprices_min = array();
220 public $multiprices_min_ttc = array();
224 public $multiprices_tva_tx = array();
228 public $multiprices_recuperableonly = array();
237 public $price_by_qty;
241 public $prices_by_qty = array();
245 public $prices_by_qty_id = array();
249 public $prices_by_qty_list = array();
259 public $multilangs = array();
264 public $default_vat_code;
279 public $remise_percent;
284 public $localtax1_tx;
288 public $localtax2_tx;
292 public $localtax1_type;
296 public $localtax2_type;
303 public $desc_supplier;
307 public $vatrate_supplier;
311 public $default_vat_code_supplier;
316 public $fourn_multicurrency_price;
320 public $fourn_multicurrency_unitprice;
324 public $fourn_multicurrency_tx;
328 public $fourn_multicurrency_id;
332 public $fourn_multicurrency_code;
354 public $qc_frequency;
361 public $stock_reel = 0;
368 public $stock_theorique;
387 public $seuil_stock_alerte = 0;
392 public $desiredstock = 0;
397 public $duration_value;
401 public $duration_unit;
410 public $fk_default_workstation;
432 public $status_buy = 0;
454 public $fk_default_bom;
461 public $product_fourn_price_id;
483 public $status_batch = 0;
490 public $sell_or_eat_by_mandatory = 0;
497 public $batch_mask =
'';
522 public $weight_units;
530 public $length_units;
546 public $height_units;
554 public $surface_units;
562 public $volume_units;
571 public $net_measure_units;
576 public $accountancy_code_sell;
580 public $accountancy_code_sell_intra;
584 public $accountancy_code_sell_export;
588 public $accountancy_code_buy;
592 public $accountancy_code_buy_intra;
596 public $accountancy_code_buy_export;
606 public $barcode_type;
611 public $barcode_type_code;
616 public $stats_propale = array();
621 public $stats_commande = array();
626 public $stats_contrat = array();
631 public $stats_facture = array();
636 public $stats_proposal_supplier = array();
641 public $stats_commande_fournisseur = array();
646 public $stats_expedition = array();
651 public $stats_reception = array();
656 public $stats_mo = array();
657 public $stats_bom = array();
658 public $stats_mrptoconsume = array();
659 public $stats_mrptoproduce = array();
660 public $stats_facturerec = array();
661 public $stats_facture_fournisseur = array();
676 public $product_fourn_id;
682 public $product_id_already_linked;
696 public $fk_default_warehouse;
701 public $fk_price_expression;
719 public $fourn_price_base_type;
736 public $ref_supplier;
750 public $price_autogen = 0;
757 public $supplierprices;
777 public $is_object_used;
788 public $is_sousproduit_qty;
800 public $is_sousproduit_incdec;
805 public $mandatory_period;
836 public $fields = array(
837 'rowid' => array(
'type' =>
'integer',
'label' =>
'TechnicalID',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'index' => 1,
'position' => 1,
'comment' =>
'Id'),
838 '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'),
839 'entity' => array(
'type' =>
'integer',
'label' =>
'Entity',
'enabled' => 1,
'visible' => 0,
'default' =>
'1',
'notnull' => 1,
'index' => 1,
'position' => 5),
840 'label' => array(
'type' =>
'varchar(255)',
'label' =>
'Label',
'enabled' => 1,
'visible' => 1,
'notnull' => 1,
'showoncombobox' => 2,
'position' => 15,
'csslist' =>
'tdoverflowmax250'),
841 'barcode' => array(
'type' =>
'varchar(255)',
'label' =>
'Barcode',
'enabled' =>
'isModEnabled("barcode")',
'position' => 20,
'visible' => -1,
'showoncombobox' => 3,
'cssview' =>
'tdwordbreak',
'csslist' =>
'tdoverflowmax125'),
842 'fk_barcode_type' => array(
'type' =>
'integer',
'label' =>
'BarcodeType',
'enabled' => 1,
'position' => 21,
'notnull' => 0,
'visible' => -1,),
843 'note_public' => array(
'type' =>
'html',
'label' =>
'NotePublic',
'enabled' => 1,
'visible' => 0,
'position' => 61),
844 'note' => array(
'type' =>
'html',
'label' =>
'NotePrivate',
'enabled' => 1,
'visible' => 0,
'position' => 62),
845 'datec' => array(
'type' =>
'datetime',
'label' =>
'DateCreation',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 500),
846 'tms' => array(
'type' =>
'timestamp',
'label' =>
'DateModification',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 501),
848 'fk_user_author' => array(
'type' =>
'integer',
'label' =>
'UserAuthor',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 510,
'foreignkey' =>
'llx_user.rowid'),
849 'fk_user_modif' => array(
'type' =>
'integer',
'label' =>
'UserModif',
'enabled' => 1,
'visible' => -2,
'notnull' => -1,
'position' => 511),
851 'localtax1_tx' => array(
'type' =>
'double(6,3)',
'label' =>
'Localtax1tx',
'enabled' => 1,
'position' => 150,
'notnull' => 0,
'visible' => -1,),
852 'localtax1_type' => array(
'type' =>
'varchar(10)',
'label' =>
'Localtax1type',
'enabled' => 1,
'position' => 155,
'notnull' => 1,
'visible' => -1,),
853 'localtax2_tx' => array(
'type' =>
'double(6,3)',
'label' =>
'Localtax2tx',
'enabled' => 1,
'position' => 160,
'notnull' => 0,
'visible' => -1,),
854 'localtax2_type' => array(
'type' =>
'varchar(10)',
'label' =>
'Localtax2type',
'enabled' => 1,
'position' => 165,
'notnull' => 1,
'visible' => -1,),
855 'last_main_doc' => array(
'type' =>
'varchar(255)',
'label' =>
'LastMainDoc',
'enabled' => 1,
'visible' => -1,
'position' => 170),
856 'import_key' => array(
'type' =>
'varchar(14)',
'label' =>
'ImportId',
'enabled' => 1,
'visible' => -2,
'notnull' => -1,
'index' => 0,
'position' => 1000),
859 'mandatory_period' => array(
'type' =>
'integer',
'label' =>
'mandatoryperiod',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'default' =>
'0',
'index' => 1,
'position' => 1000),
880 $this->ismultientitymanaged = 1;
881 $this->isextrafieldmanaged = 1;
894 $this->
ref = trim($this->
ref);
922 public function create($user, $notrigger = 0)
924 global $conf, $langs;
930 $this->
ref = trim($this->
ref);
934 $this->label = trim($this->label);
935 $this->price_ttc = (float)
price2num($this->price_ttc);
937 $this->price_min_ttc = (float)
price2num($this->price_min_ttc);
938 $this->price_min = (float)
price2num($this->price_min);
939 $this->price_label = trim($this->price_label);
940 if (empty($this->tva_tx)) {
943 if (empty($this->tva_npr)) {
947 if (empty($this->localtax1_tx)) {
948 $this->localtax1_tx = 0;
950 if (empty($this->localtax2_tx)) {
951 $this->localtax2_tx = 0;
953 if (empty($this->localtax1_type)) {
954 $this->localtax1_type =
'0';
956 if (empty($this->localtax2_type)) {
957 $this->localtax2_type =
'0';
959 if (empty($this->
price)) {
962 if (empty($this->price_min)) {
963 $this->price_min = 0;
966 if (empty($this->price_by_qty)) {
967 $this->price_by_qty = 0;
970 if (empty($this->
status)) {
973 if (empty($this->status_buy)) {
974 $this->status_buy = 0;
983 if ($this->price_base_type ==
'TTC' && $this->price_ttc > 0) {
984 $price_ttc =
price2num($this->price_ttc,
'MU');
985 $price_ht =
price2num($this->price_ttc / (1 + ($this->tva_tx / 100)),
'MU');
989 if ($this->price_base_type !=
'TTC' && $this->
price > 0) {
991 $price_ttc =
price2num($this->
price * (1 + ($this->tva_tx / 100)),
'MU');
995 if (($this->price_min_ttc > 0) && ($this->price_base_type ==
'TTC')) {
996 $price_min_ttc =
price2num($this->price_min_ttc,
'MU');
997 $price_min_ht =
price2num($this->price_min_ttc / (1 + ($this->tva_tx / 100)),
'MU');
1001 if (($this->price_min > 0) && ($this->price_base_type !=
'TTC')) {
1002 $price_min_ht =
price2num($this->price_min,
'MU');
1003 $price_min_ttc =
price2num($this->price_min * (1 + ($this->tva_tx / 100)),
'MU');
1006 $this->accountancy_code_buy = trim($this->accountancy_code_buy);
1007 $this->accountancy_code_buy_intra = trim($this->accountancy_code_buy_intra);
1008 $this->accountancy_code_buy_export = trim($this->accountancy_code_buy_export);
1009 $this->accountancy_code_sell = trim($this->accountancy_code_sell);
1010 $this->accountancy_code_sell_intra = trim($this->accountancy_code_sell_intra);
1011 $this->accountancy_code_sell_export = trim($this->accountancy_code_sell_export);
1014 $this->barcode = trim($this->barcode);
1015 $this->mandatory_period = empty($this->mandatory_period) ? 0 : $this->mandatory_period;
1017 if (empty($this->label)) {
1018 $this->error =
'ErrorMandatoryParametersNotProvided';
1022 if (empty($this->
ref) || $this->
ref ==
'auto') {
1024 $module =
getDolGlobalString(
'PRODUCT_CODEPRODUCT_ADDON',
'mod_codeproduct_leopard');
1025 if ($module !=
'mod_codeproduct_leopard') {
1026 if (substr($module, 0, 16) ==
'mod_codeproduct_' && substr($module, -3) ==
'php') {
1027 $module = substr($module, 0,
dol_strlen($module) - 4);
1030 $modCodeProduct =
new $module();
1031 '@phan-var-force ModeleProductCode $modCodeProduct';
1032 if (!empty($modCodeProduct->code_auto)) {
1033 $this->
ref = $modCodeProduct->getNextValue($this, $this->
type);
1035 unset($modCodeProduct);
1038 if (empty($this->
ref)) {
1039 $this->error =
'ProductModuleNotSetupForAutoRef';
1044 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);
1048 if (empty($this->date_creation)) {
1049 $this->date_creation = $now;
1055 if ($this->barcode ==
'-1' || $this->barcode ==
'auto') {
1056 $this->barcode = $this->
get_barcode($this, $this->barcode_type_code);
1061 $result = $this->
verify();
1064 $sql =
"SELECT count(*) as nb";
1065 $sql .=
" FROM ".$this->db->prefix().
"product";
1066 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
1067 $sql .=
" AND ref = '".$this->db->escape($this->
ref).
"'";
1069 $result = $this->db->query($sql);
1071 $obj = $this->db->fetch_object($result);
1072 if ($obj->nb == 0) {
1074 $sql =
"INSERT INTO ".$this->db->prefix().
"product (";
1078 $sql .=
", ref_ext";
1079 $sql .=
", price_min";
1080 $sql .=
", price_min_ttc";
1082 $sql .=
", fk_user_author";
1083 $sql .=
", fk_product_type";
1085 $sql .=
", price_ttc";
1086 $sql .=
", price_base_type";
1087 $sql .=
", price_label";
1091 $sql .=
", accountancy_code_buy";
1092 $sql .=
", accountancy_code_buy_intra";
1093 $sql .=
", accountancy_code_buy_export";
1094 $sql .=
", accountancy_code_sell";
1095 $sql .=
", accountancy_code_sell_intra";
1096 $sql .=
", accountancy_code_sell_export";
1099 $sql .=
", finished";
1100 $sql .=
", tobatch";
1101 $sql .=
", sell_or_eat_by_mandatory";
1102 $sql .=
", batch_mask";
1103 $sql .=
", fk_unit";
1104 $sql .=
", mandatory_period";
1105 $sql .=
") VALUES (";
1106 $sql .=
"'".$this->db->idate($this->date_creation).
"'";
1107 $sql .=
", ".(!empty($this->entity) ? (int) $this->entity : (int) $conf->entity);
1108 $sql .=
", '".$this->db->escape($this->
ref).
"'";
1109 $sql .=
", ".(!empty($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
1110 $sql .=
", ".price2num($price_min_ht);
1111 $sql .=
", ".price2num($price_min_ttc);
1112 $sql .=
", ".(!empty($this->label) ?
"'".$this->db->escape($this->label).
"'" :
"null");
1113 $sql .=
", ".((int) $user->id);
1114 $sql .=
", ".((int) $this->
type);
1115 $sql .=
", ".price2num($price_ht,
'MT');
1116 $sql .=
", ".price2num($price_ttc,
'MT');
1117 $sql .=
", '".$this->db->escape($this->price_base_type).
"'";
1118 $sql .=
", ".(!empty($this->price_label) ?
"'".$this->db->escape($this->price_label).
"'" :
"null");
1119 $sql .=
", ".((int) $this->
status);
1120 $sql .=
", ".((int) $this->status_buy);
1122 $sql .=
", '".$this->db->escape($this->accountancy_code_buy).
"'";
1123 $sql .=
", '".$this->db->escape($this->accountancy_code_buy_intra).
"'";
1124 $sql .=
", '".$this->db->escape($this->accountancy_code_buy_export).
"'";
1125 $sql .=
", '".$this->db->escape($this->accountancy_code_sell).
"'";
1126 $sql .=
", '".$this->db->escape($this->accountancy_code_sell_intra).
"'";
1127 $sql .=
", '".$this->db->escape($this->accountancy_code_sell_export).
"'";
1129 $sql .=
", '".$this->db->escape($this->canvas).
"'";
1130 $sql .=
", ".((!isset($this->finished) || $this->finished < 0 || $this->finished ==
'') ?
'NULL' : (int) $this->finished);
1131 $sql .=
", ".((empty($this->status_batch) || $this->status_batch < 0) ?
'0' : ((int) $this->status_batch));
1132 $sql .=
", ".((empty($this->sell_or_eat_by_mandatory) || $this->sell_or_eat_by_mandatory < 0) ? 0 : ((int) $this->sell_or_eat_by_mandatory));
1133 $sql .=
", '".$this->db->escape($this->batch_mask).
"'";
1134 $sql .=
", ".($this->fk_unit > 0 ? ((int) $this->fk_unit) :
'NULL');
1135 $sql .=
", '".$this->db->escape($this->mandatory_period).
"'";
1138 dol_syslog(get_class($this).
"::Create", LOG_DEBUG);
1140 $result = $this->db->query($sql);
1142 $id = $this->db->last_insert_id($this->db->prefix().
"product");
1146 $this->
price = $price_ht;
1147 $this->price_ttc = $price_ttc;
1148 $this->price_min = $price_min_ht;
1149 $this->price_min_ttc = $price_min_ttc;
1153 if ($this->
update($id, $user, 1,
'add') <= 0) {
1158 $this->error = $this->db->lasterror();
1163 $this->db->query(
"DELETE FROM " . $this->db->prefix() .
"product_perentity WHERE fk_product = " .((int) $this->id) .
" AND entity = " . ((
int) $conf->entity));
1165 $sql =
"INSERT INTO " . $this->db->prefix() .
"product_perentity (";
1166 $sql .=
" fk_product";
1168 $sql .=
", accountancy_code_buy";
1169 $sql .=
", accountancy_code_buy_intra";
1170 $sql .=
", accountancy_code_buy_export";
1171 $sql .=
", accountancy_code_sell";
1172 $sql .=
", accountancy_code_sell_intra";
1173 $sql .=
", accountancy_code_sell_export";
1174 $sql .=
") VALUES (";
1176 $sql .=
", " . ((int) $conf->entity);
1177 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy) .
"'";
1178 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_intra) .
"'";
1179 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_export) .
"'";
1180 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell) .
"'";
1181 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_intra) .
"'";
1182 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_export) .
"'";
1184 $result = $this->db->query($sql);
1187 $this->error =
'ErrorFailedToInsertAccountancyForEntity';
1192 $this->error =
'ErrorFailedToGetInsertedId';
1196 $this->error = $this->db->lasterror();
1200 $langs->load(
"products");
1202 $this->error =
"ErrorProductAlreadyExists";
1203 dol_syslog(get_class($this).
"::Create fails, ref ".$this->
ref.
" already exists");
1207 $this->error = $this->db->lasterror();
1210 if (!$error && !$notrigger) {
1212 $result = $this->
call_trigger(
'PRODUCT_CREATE', $user);
1220 $this->db->commit();
1223 $this->db->rollback();
1227 $this->db->rollback();
1228 dol_syslog(get_class($this).
"::Create fails verify ".implode(
',', $this->errors), LOG_WARNING);
1244 $this->errors = array();
1247 $this->
ref = trim($this->
ref);
1250 $this->errors[] =
'ErrorBadRef';
1254 $arrayofnonnegativevalue = array(
'weight' =>
'Weight',
'width' =>
'Width',
'height' =>
'Height',
'length' =>
'Length',
'surface' =>
'Surface',
'volume' =>
'Volume');
1255 foreach ($arrayofnonnegativevalue as $key => $value) {
1256 if (property_exists($this, $key) && !empty($this->$key) && ($this->$key < 0)) {
1257 $langs->loadLangs(array(
"main",
"other"));
1258 $this->error = $langs->trans(
"FieldCannotBeNegative", $langs->transnoentitiesnoconv($value));
1259 $this->errors[] = $this->error;
1264 $rescode = $this->
check_barcode($this->barcode, $this->barcode_type_code);
1266 if ($rescode == -1) {
1267 $this->errors[] =
'ErrorBadBarCodeSyntax';
1268 } elseif ($rescode == -2) {
1269 $this->errors[] =
'ErrorBarCodeRequired';
1270 } elseif ($rescode == -3) {
1272 $this->errors[] =
'ErrorBarCodeAlreadyUsed';
1300 $dirsociete = array_merge(array(
'/core/modules/barcode/'), $conf->modules_parts[
'barcode']);
1301 foreach ($dirsociete as $dirroot) {
1308 $mod =
new $module();
1309 '@phan-var-force ModeleNumRefBarCode $mod';
1311 dol_syslog(get_class($this).
"::check_barcode value=".$valuetotest.
" type=".$typefortest.
" module=".$module);
1312 $result = $mod->verif($this->db, $valuetotest, $this, 0, $typefortest);
1330 public function update($id, $user, $notrigger = 0, $action =
'update', $updatetype =
false)
1332 global $langs, $conf, $hookmanager;
1337 if (!$this->label) {
1338 $this->label =
'MISSING LABEL';
1343 $this->
ref = trim($this->
ref);
1347 $this->label = trim($this->label);
1349 $this->note_private = (isset($this->note_private) ? trim($this->note_private) :
null);
1350 $this->note_public = (isset($this->note_public) ? trim($this->note_public) :
null);
1351 $this->net_measure =
price2num($this->net_measure);
1352 $this->net_measure_units = (empty($this->net_measure_units) ?
'' : trim((
string) $this->net_measure_units));
1353 $this->weight =
price2num($this->weight);
1354 $this->weight_units = (empty($this->weight_units) ?
'' : trim((
string) $this->weight_units));
1355 $this->length =
price2num($this->length);
1356 $this->length_units = (empty($this->length_units) ?
'' : trim((
string) $this->length_units));
1358 $this->width_units = (empty($this->width_units) ?
'' : trim((
string) $this->width_units));
1359 $this->height =
price2num($this->height);
1360 $this->height_units = (empty($this->height_units) ?
'' : trim((
string) $this->height_units));
1361 $this->surface =
price2num($this->surface);
1362 $this->surface_units = (empty($this->surface_units) ?
'' : trim((
string) $this->surface_units));
1363 $this->volume =
price2num($this->volume);
1364 $this->volume_units = (empty($this->volume_units) ?
'' : trim((
string) $this->volume_units));
1367 if (is_numeric($this->length_units)) {
1368 $this->width_units = $this->length_units;
1370 if (is_numeric($this->length_units)) {
1371 $this->height_units = $this->length_units;
1375 if (empty($this->surface) && !empty($this->length) && !empty($this->width) && $this->length_units == $this->width_units) {
1376 $this->surface = (float) $this->length * (
float) $this->width;
1379 if (empty($this->volume) && !empty($this->surface) && !empty($this->height) && $this->length_units == $this->height_units) {
1380 $this->volume = $this->surface * (float) $this->height;
1384 if (empty($this->tva_tx)) {
1387 if (empty($this->tva_npr)) {
1390 if (empty($this->localtax1_tx)) {
1391 $this->localtax1_tx = 0;
1393 if (empty($this->localtax2_tx)) {
1394 $this->localtax2_tx = 0;
1396 if (empty($this->localtax1_type)) {
1397 $this->localtax1_type =
'0';
1399 if (empty($this->localtax2_type)) {
1400 $this->localtax2_type =
'0';
1402 if (empty($this->
status)) {
1405 if (empty($this->status_buy)) {
1406 $this->status_buy = 0;
1409 if (empty($this->country_id)) {
1410 $this->country_id = 0;
1413 if (empty($this->state_id)) {
1414 $this->state_id = 0;
1418 $this->barcode = (empty($this->barcode) ?
'' : trim($this->barcode));
1420 $this->accountancy_code_buy = trim($this->accountancy_code_buy);
1421 $this->accountancy_code_buy_intra = (!empty($this->accountancy_code_buy_intra) ? trim($this->accountancy_code_buy_intra) :
'');
1422 $this->accountancy_code_buy_export = trim($this->accountancy_code_buy_export);
1423 $this->accountancy_code_sell = trim($this->accountancy_code_sell);
1424 $this->accountancy_code_sell_intra = trim($this->accountancy_code_sell_intra);
1425 $this->accountancy_code_sell_export = trim($this->accountancy_code_sell_export);
1432 if ($action !=
'add') {
1433 $result = $this->
verify();
1441 if (is_null($this->oldcopy) || (is_object($this->oldcopy) && $this->oldcopy->isEmpty())) {
1446 if ($this->
hasbatch() && !$this->oldcopy->hasbatch()) {
1448 $valueforundefinedlot =
'000000';
1453 dol_syslog(
"Flag batch of product id=".$this->
id.
" is set to ON, so we will create missing records into product_batch");
1456 foreach ($this->stock_warehouse as $idW => $ObjW) {
1458 foreach ($ObjW->detail_batch as $detail) {
1459 if ($detail->batch == $valueforundefinedlot || $detail->batch ==
'Undefined') {
1461 $sqlclean =
"DELETE FROM ".$this->db->prefix().
"product_batch WHERE batch in('Undefined', '".$this->db->escape($valueforundefinedlot).
"') AND fk_product_stock = ".((int) $ObjW->id);
1462 $result = $this->db->query($sqlclean);
1470 $qty_batch += $detail->qty;
1474 if ($ObjW->real != $qty_batch) {
1476 $ObjBatch->batch = $valueforundefinedlot;
1477 $ObjBatch->qty = ($ObjW->real - $qty_batch);
1478 $ObjBatch->fk_product_stock = $ObjW->id;
1480 if ($ObjBatch->create($user, 1) < 0) {
1482 $this->errors = $ObjBatch->errors;
1487 if ($ObjLot->fetch(0, $this->id, $valueforundefinedlot) == 0) {
1488 $ObjLot->fk_product = $this->id;
1489 $ObjLot->entity = $this->entity;
1490 $ObjLot->fk_user_creat = $user->id;
1491 $ObjLot->batch = $valueforundefinedlot;
1492 if ($ObjLot->create($user,
true) < 0) {
1494 $this->errors = $ObjLot->errors;
1503 if ($this->barcode == -1) {
1504 $this->barcode = $this->
get_barcode($this, $this->barcode_type_code);
1507 $sql =
"UPDATE ".$this->db->prefix().
"product";
1508 $sql .=
" SET label = '".$this->db->escape($this->label).
"'";
1511 $sql .=
", fk_product_type = ".((int) $this->
type);
1514 $sql .=
", ref = '".$this->db->escape($this->
ref).
"'";
1515 $sql .=
", ref_ext = ".(!empty($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
1516 $sql .=
", default_vat_code = ".($this->default_vat_code ?
"'".$this->db->escape($this->default_vat_code).
"'" :
"null");
1517 $sql .=
", tva_tx = ".((float) $this->tva_tx);
1518 $sql .=
", recuperableonly = ".((int) $this->tva_npr);
1519 $sql .=
", localtax1_tx = ".((float) $this->localtax1_tx);
1520 $sql .=
", localtax2_tx = ".((float) $this->localtax2_tx);
1521 $sql .=
", localtax1_type = ".($this->localtax1_type !=
'' ?
"'".$this->db->escape($this->localtax1_type).
"'" :
"'0'");
1522 $sql .=
", localtax2_type = ".($this->localtax2_type !=
'' ?
"'".$this->db->escape($this->localtax2_type).
"'" :
"'0'");
1524 $sql .=
", barcode = ".(empty($this->barcode) ?
"null" :
"'".$this->db->escape($this->barcode).
"'");
1525 $sql .=
", fk_barcode_type = ".(empty($this->barcode_type) ?
"null" : $this->db->escape($this->barcode_type));
1527 $sql .=
", tosell = ".(int) $this->
status;
1528 $sql .=
", tobuy = ".(int) $this->status_buy;
1529 $sql .=
", tobatch = ".((empty($this->status_batch) || $this->status_batch < 0) ?
'0' : (int) $this->status_batch);
1530 $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);
1531 $sql .=
", batch_mask = '".$this->db->escape($this->batch_mask).
"'";
1533 $sql .=
", finished = ".((!isset($this->finished) || $this->finished < 0 || $this->finished ==
'') ?
"null" : (int) $this->finished);
1534 $sql .=
", fk_default_bom = ".((!isset($this->fk_default_bom) || $this->fk_default_bom < 0 || $this->fk_default_bom ==
'') ?
"null" : (int) $this->fk_default_bom);
1535 $sql .=
", net_measure = ".($this->net_measure !=
'' ?
"'".$this->db->escape($this->net_measure).
"'" :
'null');
1536 $sql .=
", net_measure_units = ".($this->net_measure_units !=
'' ?
"'".$this->db->escape($this->net_measure_units).
"'" :
'null');
1537 $sql .=
", weight = ".($this->weight !=
'' ?
"'".$this->db->escape($this->weight).
"'" :
'null');
1538 $sql .=
", weight_units = ".($this->weight_units !=
'' ?
"'".$this->db->escape($this->weight_units).
"'" :
'null');
1539 $sql .=
", length = ".($this->length !=
'' ?
"'".$this->db->escape($this->length).
"'" :
'null');
1540 $sql .=
", length_units = ".($this->length_units !=
'' ?
"'".$this->db->escape($this->length_units).
"'" :
'null');
1541 $sql .=
", width= ".($this->width !=
'' ?
"'".$this->db->escape($this->width).
"'" :
'null');
1542 $sql .=
", width_units = ".($this->width_units !=
'' ?
"'".$this->db->escape($this->width_units).
"'" :
'null');
1543 $sql .=
", height = ".($this->height !=
'' ?
"'".$this->db->escape($this->height).
"'" :
'null');
1544 $sql .=
", height_units = ".($this->height_units !=
'' ?
"'".$this->db->escape($this->height_units).
"'" :
'null');
1545 $sql .=
", surface = ".($this->surface !=
'' ?
"'".$this->db->escape($this->surface).
"'" :
'null');
1546 $sql .=
", surface_units = ".($this->surface_units !=
'' ?
"'".$this->db->escape($this->surface_units).
"'" :
'null');
1547 $sql .=
", volume = ".($this->volume !=
'' ?
"'".$this->db->escape($this->volume).
"'" :
'null');
1548 $sql .=
", volume_units = ".($this->volume_units !=
'' ?
"'".$this->db->escape($this->volume_units).
"'" :
'null');
1549 $sql .=
", fk_default_warehouse = ".($this->fk_default_warehouse > 0 ? ((int) $this->fk_default_warehouse) :
'null');
1550 $sql .=
", fk_default_workstation = ".($this->fk_default_workstation > 0 ? ((int) $this->fk_default_workstation) :
'null');
1551 $sql .=
", seuil_stock_alerte = ".((isset($this->seuil_stock_alerte) && is_numeric($this->seuil_stock_alerte)) ? (
float) $this->seuil_stock_alerte :
'null');
1552 $sql .=
", description = '".$this->db->escape($this->
description).
"'";
1553 $sql .=
", url = ".($this->url ?
"'".$this->db->escape($this->url).
"'" :
'null');
1554 $sql .=
", customcode = '".$this->db->escape($this->customcode).
"'";
1555 $sql .=
", fk_country = ".($this->country_id > 0 ? (int) $this->country_id :
'null');
1556 $sql .=
", fk_state = ".($this->state_id > 0 ? (int) $this->state_id :
'null');
1557 $sql .=
", lifetime = ".($this->lifetime > 0 ? (int) $this->lifetime :
'null');
1558 $sql .=
", qc_frequency = ".($this->qc_frequency > 0 ? (int) $this->qc_frequency :
'null');
1559 $sql .=
", note = ".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
'null');
1560 $sql .=
", note_public = ".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
'null');
1561 $sql .=
", duration = '".$this->db->escape($this->duration_value.$this->duration_unit).
"'";
1563 $sql .=
", accountancy_code_buy = '" . $this->db->escape($this->accountancy_code_buy) .
"'";
1564 $sql .=
", accountancy_code_buy_intra = '" . $this->db->escape($this->accountancy_code_buy_intra) .
"'";
1565 $sql .=
", accountancy_code_buy_export = '" . $this->db->escape($this->accountancy_code_buy_export) .
"'";
1566 $sql .=
", accountancy_code_sell= '" . $this->db->escape($this->accountancy_code_sell) .
"'";
1567 $sql .=
", accountancy_code_sell_intra= '" . $this->db->escape($this->accountancy_code_sell_intra) .
"'";
1568 $sql .=
", accountancy_code_sell_export= '" . $this->db->escape($this->accountancy_code_sell_export) .
"'";
1570 $sql .=
", desiredstock = ".((isset($this->desiredstock) && is_numeric($this->desiredstock)) ? (
float) $this->desiredstock :
"null");
1571 $sql .=
", cost_price = ".($this->cost_price !=
'' ? $this->db->escape($this->cost_price) :
'null');
1572 $sql .=
", fk_unit= ".(!$this->fk_unit ?
'NULL' : (int) $this->fk_unit);
1573 $sql .=
", price_autogen = ".(!$this->price_autogen ? 0 : 1);
1574 $sql .=
", fk_price_expression = ".($this->fk_price_expression != 0 ? (int) $this->fk_price_expression :
'NULL');
1575 $sql .=
", fk_user_modif = ".($user->id > 0 ? $user->id :
'NULL');
1576 $sql .=
", mandatory_period = ".($this->mandatory_period);
1578 $sql .=
" WHERE rowid = ".((int) $id);
1580 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
1582 $resql = $this->db->query($sql);
1589 $this->db->rollback();
1598 $this->db->query(
"DELETE FROM " . $this->db->prefix() .
"product_perentity WHERE fk_product = " . ((
int) $this->id) .
" AND entity = " . ((
int) $conf->entity));
1600 $sql =
"INSERT INTO " . $this->db->prefix() .
"product_perentity (";
1601 $sql .=
" fk_product";
1603 $sql .=
", accountancy_code_buy";
1604 $sql .=
", accountancy_code_buy_intra";
1605 $sql .=
", accountancy_code_buy_export";
1606 $sql .=
", accountancy_code_sell";
1607 $sql .=
", accountancy_code_sell_intra";
1608 $sql .=
", accountancy_code_sell_export";
1609 $sql .=
") VALUES (";
1610 $sql .= ((int) $this->
id);
1611 $sql .=
", " . ((int) $conf->entity);
1612 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy) .
"'";
1613 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_intra) .
"'";
1614 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_export) .
"'";
1615 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell) .
"'";
1616 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_intra) .
"'";
1617 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_export) .
"'";
1619 $result = $this->db->query($sql);
1622 $this->error =
'ErrorFailedToUpdateAccountancyForEntity';
1626 if (!$this->
hasbatch() && $this->oldcopy->hasbatch()) {
1628 $sql =
'SELECT pb.qty, ps.fk_entrepot, pb.batch FROM '.MAIN_DB_PREFIX.
'product_batch as pb';
1629 $sql .=
' INNER JOIN '.MAIN_DB_PREFIX.
'product_stock as ps ON (ps.rowid = pb.fk_product_stock)';
1630 $sql .=
' WHERE ps.fk_product = '.(int) $this->
id;
1632 $resql = $this->db->query($sql);
1636 while ($obj = $this->db->fetch_object($resql)) {
1638 $fk_entrepot = $obj->fk_entrepot;
1642 $batch = $obj->batch;
1645 $addOremove = $value > 0 ? 1 : 0;
1646 $label = $langs->trans(
'BatchStockMouvementAddInGlobal');
1647 $res = $this->
correct_stock_batch($user, $fk_entrepot, abs($value), $addOremove, $label, $price, $dlc, $dluo, $batch, $inventorycode,
'',
null, 0,
null,
true);
1650 $label = $langs->trans(
'BatchStockMouvementAddInGlobal');
1651 $res = $this->
correct_stock($user, $fk_entrepot, abs($value), (
int) empty($addOremove), $label, $price, $inventorycode,
'',
null, 0);
1670 if (!$error && !$notrigger) {
1672 $result = $this->
call_trigger(
'PRODUCT_MODIFY', $user);
1679 if (!$error && (is_object($this->oldcopy) && $this->oldcopy->ref !== $this->ref)) {
1681 if ($conf->product->dir_output) {
1684 if (file_exists($olddir)) {
1688 $res = @rename($olddir, $newdir);
1690 $langs->load(
"errors");
1691 $this->error = $langs->trans(
'ErrorFailToRenameDir', $olddir, $newdir);
1695 require_once DOL_DOCUMENT_ROOT .
'/ecm/class/ecmfiles.class.php';
1696 $ecmfiles =
new EcmFiles($this->db);
1697 $ecmfiles->updateAfterRename(
"produit/".
dol_sanitizeFileName($this->oldcopy->ref),
"produit/".dol_sanitizeFileName($this->ref));
1704 if (isModEnabled(
'variants')) {
1705 include_once DOL_DOCUMENT_ROOT.
'/variants/class/ProductCombination.class.php';
1709 foreach ($comb->fetchAllByFkProductParent($this->id) as $currcomb) {
1710 $currcomb->updateProperties($this, $user);
1714 $this->db->commit();
1717 $this->db->rollback();
1721 if ($this->db->errno() ==
'DB_ERROR_RECORD_ALREADY_EXISTS') {
1722 $langs->load(
"errors");
1723 if (empty($conf->barcode->enabled) || empty($this->barcode)) {
1724 $this->error = $langs->trans(
"Error").
" : ".$langs->trans(
"ErrorProductAlreadyExists", $this->
ref);
1726 $this->error = $langs->trans(
"Error").
" : ".$langs->trans(
"ErrorProductBarCodeAlreadyExists", $this->barcode);
1728 $this->errors[] = $this->error;
1729 $this->db->rollback();
1732 $this->error = $langs->trans(
"Error").
" : ".$this->db->error().
" - ".$sql;
1733 $this->errors[] = $this->error;
1734 $this->db->rollback();
1739 $this->db->rollback();
1740 dol_syslog(get_class($this).
"::Update fails verify ".implode(
',', $this->errors), LOG_WARNING);
1752 public function delete(
User $user, $notrigger = 0)
1755 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1760 if (empty($this->
id)) {
1761 $this->error =
"Object must be fetched before calling delete";
1764 if (($this->
isProduct() && !$user->
hasRight(
'produit',
'supprimer')) || ($this->isService() && !$user->hasRight(
'service',
'supprimer'))) {
1765 $this->error =
"ErrorForbidden";
1770 if (empty($objectisused)) {
1773 if (!$error && empty($notrigger)) {
1775 $result = $this->
call_trigger(
'PRODUCT_DELETE', $user);
1784 $sql =
"DELETE FROM ".$this->db->prefix().
'product_batch';
1785 $sql .=
" WHERE fk_product_stock IN (";
1786 $sql .=
"SELECT rowid FROM ".$this->db->prefix().
'product_stock';
1787 $sql .=
" WHERE fk_product = ".((int) $this->
id).
")";
1789 $result = $this->db->query($sql);
1792 $this->errors[] = $this->db->lasterror();
1798 $elements = array(
'product_fournisseur_price',
'product_price',
'product_lang',
'categorie_product',
'product_stock',
'product_customer_price',
'product_lot');
1799 foreach ($elements as $table) {
1801 $sql =
"DELETE FROM ".$this->db->prefix().$table;
1802 $sql .=
" WHERE fk_product = ".(int) $this->
id;
1804 $result = $this->db->query($sql);
1807 $this->errors[] = $this->db->lasterror();
1814 include_once DOL_DOCUMENT_ROOT.
'/variants/class/ProductCombination.class.php';
1815 include_once DOL_DOCUMENT_ROOT.
'/variants/class/ProductCombination2ValuePair.class.php';
1820 if ($prodcomb->deleteByFkProductParent($user, $this->id) < 0) {
1822 $this->errors[] =
'Error deleting combinations';
1826 if (!$error && ($prodcomb->fetchByFkProductChild($this->id) > 0) && ($prodcomb->delete($user) < 0)) {
1828 $this->errors[] =
'Error deleting child combination';
1834 $sql =
"DELETE FROM ".$this->db->prefix().
"product_association";
1835 $sql .=
" WHERE fk_product_pere = ".(int) $this->
id.
" OR fk_product_fils = ".(
int) $this->id;
1837 $result = $this->db->query($sql);
1840 $this->errors[] = $this->db->lasterror();
1849 dol_syslog(get_class($this).
"::delete error -4 ".$this->error, LOG_ERR);
1855 $sqlz =
"DELETE FROM ".$this->db->prefix().
"product";
1856 $sqlz .=
" WHERE rowid = ".(int) $this->
id;
1858 $resultz = $this->db->query($sqlz);
1861 $this->errors[] = $this->db->lasterror();
1877 if ($conf->product->dir_output) {
1878 $dir = $conf->product->dir_output.
"/".$ref;
1879 if (file_exists($dir)) {
1882 $this->errors[] =
'ErrorFailToDeleteDir';
1890 $this->db->commit();
1893 foreach ($this->errors as $errmsg) {
1894 dol_syslog(get_class($this).
"::delete ".$errmsg, LOG_ERR);
1895 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1897 $this->db->rollback();
1901 $this->error =
"ErrorRecordIsUsedCantDelete";
1915 $sellByLabel = $langs->trans(
'SellByDate');
1916 $eatByLabel = $langs->trans(
'EatByDate');
1918 self::SELL_OR_EAT_BY_MANDATORY_ID_NONE => $langs->trans(
'BatchSellOrEatByMandatoryNone'),
1919 self::SELL_OR_EAT_BY_MANDATORY_ID_SELL_BY => $sellByLabel,
1920 self::SELL_OR_EAT_BY_MANDATORY_ID_EAT_BY => $eatByLabel,
1921 self::SELL_OR_EAT_BY_MANDATORY_ID_SELL_AND_EAT => $langs->trans(
'BatchSellOrEatByMandatoryAll', $sellByLabel, $eatByLabel),
1932 $sellOrEatByMandatoryLabel =
'';
1935 if (isset($sellOrEatByMandatoryList[$this->sell_or_eat_by_mandatory])) {
1936 $sellOrEatByMandatoryLabel = $sellOrEatByMandatoryList[$this->sell_or_eat_by_mandatory];
1939 return $sellOrEatByMandatoryLabel;
1952 $langs_available = $langs->get_available_languages(DOL_DOCUMENT_ROOT, 0, 2);
1953 $current_lang = $langs->getDefaultLang();
1955 foreach ($langs_available as $key => $value) {
1956 if ($key == $current_lang) {
1957 $sql =
"SELECT rowid";
1958 $sql .=
" FROM ".$this->db->prefix().
"product_lang";
1959 $sql .=
" WHERE fk_product = ".((int) $this->
id);
1960 $sql .=
" AND lang = '".$this->db->escape($key).
"'";
1962 $result = $this->db->query($sql);
1964 if ($this->db->num_rows($result)) {
1965 $sql2 =
"UPDATE ".$this->db->prefix().
"product_lang";
1967 $sql2 .=
" label='".$this->db->escape($this->label).
"',";
1968 $sql2 .=
" description='".$this->db->escape($this->
description).
"'";
1970 $sql2 .=
", note='".$this->db->escape($this->other).
"'";
1972 $sql2 .=
" WHERE fk_product = ".((int) $this->
id).
" AND lang = '".$this->db->escape($key).
"'";
1974 $sql2 =
"INSERT INTO ".$this->db->prefix().
"product_lang (fk_product, lang, label, description";
1979 $sql2 .=
" VALUES(".((int) $this->
id).
",'".$this->db->escape($key).
"','".$this->db->escape($this->label).
"',";
1980 $sql2 .=
" '".$this->db->escape($this->
description).
"'";
1982 $sql2 .=
", '".$this->db->escape($this->other).
"'";
1986 dol_syslog(get_class($this).
'::setMultiLangs key = current_lang = '.$key);
1987 if (!$this->db->query($sql2)) {
1988 $this->error = $this->db->lasterror();
1991 } elseif (isset($this->multilangs[$key])) {
1992 if (empty($this->multilangs[$key][
"label"])) {
1993 $this->errors[] = $key .
' : ' . $langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv(
"Label"));
1997 $sql =
"SELECT rowid";
1998 $sql .=
" FROM ".$this->db->prefix().
"product_lang";
1999 $sql .=
" WHERE fk_product = ".((int) $this->
id);
2000 $sql .=
" AND lang = '".$this->db->escape($key).
"'";
2002 $result = $this->db->query($sql);
2004 if ($this->db->num_rows($result)) {
2005 $sql2 =
"UPDATE ".$this->db->prefix().
"product_lang";
2007 $sql2 .=
" label = '".$this->db->escape($this->multilangs[
"$key"][
"label"]).
"',";
2008 $sql2 .=
" description = '".$this->db->escape($this->multilangs[
"$key"][
"description"]).
"'";
2011 $sql2 .=
", note = '".$this->db->escape($this->multilangs[
"$key"][
"other"]).
"'";
2013 $sql2 .=
" WHERE fk_product = ".((int) $this->
id).
" AND lang = '".$this->db->escape($key).
"'";
2015 $sql2 =
"INSERT INTO ".$this->db->prefix().
"product_lang (fk_product, lang, label, description";
2020 $sql2 .=
" VALUES(".((int) $this->
id).
",'".$this->db->escape($key).
"','".$this->db->escape($this->multilangs[
"$key"][
"label"]).
"',";
2021 $sql2 .=
" '".$this->db->escape($this->multilangs[
"$key"][
"description"]).
"'";
2024 $sql2 .=
", '".$this->db->escape($this->multilangs[
"$key"][
"other"]).
"'";
2030 if ($this->multilangs[
"$key"][
"label"] || $this->multilangs[
"$key"][
"description"]) {
2031 if (!$this->db->query($sql2)) {
2032 $this->error = $this->db->lasterror();
2042 $result = $this->
call_trigger(
'PRODUCT_SET_MULTILANGS', $user);
2044 $this->error = $this->db->lasterror();
2062 $sql =
"DELETE FROM ".$this->db->prefix().
"product_lang";
2063 $sql .=
" WHERE fk_product = ".((int) $this->
id).
" AND lang = '".$this->db->escape($langtodelete).
"'";
2065 dol_syslog(get_class($this).
'::delMultiLangs', LOG_DEBUG);
2066 $result = $this->db->query($sql);
2069 $result = $this->
call_trigger(
'PRODUCT_DEL_MULTILANGS', $user);
2071 $this->error = $this->db->lasterror();
2072 dol_syslog(get_class($this).
'::delMultiLangs error='.$this->error, LOG_ERR);
2078 $this->error = $this->db->lasterror();
2079 dol_syslog(get_class($this).
'::delMultiLangs error='.$this->error, LOG_ERR);
2100 if ($type ==
'buy') {
2101 $field =
'accountancy_code_buy';
2102 } elseif ($type ==
'buy_intra') {
2103 $field =
'accountancy_code_buy_intra';
2104 } elseif ($type ==
'buy_export') {
2105 $field =
'accountancy_code_buy_export';
2106 } elseif ($type ==
'sell') {
2107 $field =
'accountancy_code_sell';
2108 } elseif ($type ==
'sell_intra') {
2109 $field =
'accountancy_code_sell_intra';
2110 } elseif ($type ==
'sell_export') {
2111 $field =
'accountancy_code_sell_export';
2116 $sql =
"UPDATE ".$this->db->prefix().$this->table_element.
" SET ";
2117 $sql .=
"$field = '".$this->db->escape($value).
"'";
2118 $sql .=
" WHERE rowid = ".((int) $this->
id);
2121 $resql = $this->db->query($sql);
2125 $result = $this->
call_trigger(
'PRODUCT_MODIFY', $user);
2132 $this->db->rollback();
2136 $this->$field = $value;
2138 $this->db->commit();
2141 $this->error = $this->db->lasterror();
2142 $this->db->rollback();
2156 $current_lang = $langs->getDefaultLang();
2158 $sql =
"SELECT lang, label, description, note as other";
2159 $sql .=
" FROM ".$this->db->prefix().
"product_lang";
2160 $sql .=
" WHERE fk_product = ".((int) $this->
id);
2162 $result = $this->db->query($sql);
2164 while ($obj = $this->db->fetch_object($result)) {
2166 if ($obj->lang == $current_lang) {
2167 $this->label = $obj->label;
2169 $this->other = $obj->other;
2171 $this->multilangs[(string) $obj->lang][
"label"] = $obj->label;
2172 $this->multilangs[(string) $obj->lang][
"description"] = $obj->description;
2173 $this->multilangs[(string) $obj->lang][
"other"] = $obj->other;
2177 $this->error =
"Error: ".$this->db->lasterror().
" - ".$sql;
2190 $testExit = array(
'multiprices',
'multiprices_ttc',
'multiprices_base_type',
'multiprices_min',
'multiprices_min_ttc',
'multiprices_tva_tx',
'multiprices_recuperableonly');
2192 foreach ($testExit as $field) {
2193 if (!isset($this->$field)) {
2196 $tmparray = $this->$field;
2197 if (!isset($tmparray[$level])) {
2203 'level' => $level ? $level : 1,
2204 'multiprices' => (float) $this->multiprices[$level],
2205 'multiprices_ttc' => (
float) $this->multiprices_ttc[$level],
2206 'multiprices_base_type' => $this->multiprices_base_type[$level],
2207 'multiprices_min' => (float) $this->multiprices_min[$level],
2208 'multiprices_min_ttc' => (
float) $this->multiprices_min_ttc[$level],
2209 'multiprices_tva_tx' => (float) $this->multiprices_tva_tx[$level],
2210 'multiprices_recuperableonly' => (
float) $this->multiprices_recuperableonly[$level],
2233 if (empty($this->price_by_qty)) {
2234 $this->price_by_qty = 0;
2238 $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,";
2239 $sql .=
" localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, price_min,price_min_ttc,price_by_qty,entity,fk_price_expression) ";
2240 $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).
",";
2241 $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');
2244 dol_syslog(get_class($this).
"::_log_price", LOG_DEBUG);
2245 $resql = $this->db->query($sql);
2247 $this->error = $this->db->lasterror();
2267 $sql =
"DELETE FROM ".$this->db->prefix().
"product_price_by_qty";
2268 $sql .=
" WHERE fk_product_price = ".((int) $rowid);
2269 $resql = $this->db->query($sql);
2271 $sql =
"DELETE FROM ".$this->db->prefix().
"product_price";
2272 $sql .=
" WHERE rowid=".((int) $rowid);
2273 $resql = $this->db->query($sql);
2277 $this->error = $this->db->lasterror();
2292 public function getSellPrice($thirdparty_seller, $thirdparty_buyer, $pqp = 0)
2294 global $hookmanager, $action;
2297 if (is_object($hookmanager)) {
2298 $parameters = array(
'thirdparty_seller' => $thirdparty_seller,
'thirdparty_buyer' => $thirdparty_buyer,
'pqp' => $pqp);
2300 $reshook = $hookmanager->executeHooks(
'getSellPrice', $parameters, $this, $action);
2302 return $hookmanager->resArray;
2307 $tva_tx =
get_default_tva($thirdparty_seller, $thirdparty_buyer, $this->
id);
2308 $tva_npr =
get_default_npr($thirdparty_seller, $thirdparty_buyer, $this->
id);
2309 if (empty($tva_tx)) {
2313 $pu_ht = $this->price;
2314 $pu_ttc = $this->price_ttc;
2315 $price_min = $this->price_min;
2316 $price_base_type = $this->price_base_type;
2320 require_once DOL_DOCUMENT_ROOT.
'/product/class/productcustomerprice.class.php';
2324 $filter = array(
't.fk_product' => $this->
id,
't.fk_soc' => $thirdparty_buyer->id);
2327 $pricebycustomerexist =
false;
2328 $result = $prodcustprice->fetchAll(
'',
'', 0, 0, $filter);
2330 if (count($prodcustprice->lines) > 0) {
2331 $pricebycustomerexist =
true;
2332 $pu_ht =
price($prodcustprice->lines[0]->price);
2333 $price_min =
price($prodcustprice->lines[0]->price_min);
2334 $pu_ttc =
price($prodcustprice->lines[0]->price_ttc);
2335 $price_base_type = $prodcustprice->lines[0]->price_base_type;
2336 $tva_tx = $prodcustprice->lines[0]->tva_tx;
2337 if ($prodcustprice->lines[0]->default_vat_code && !preg_match(
'/\(.*\)/', $tva_tx)) {
2338 $tva_tx .=
' ('.$prodcustprice->lines[0]->default_vat_code.
')';
2340 $tva_npr = $prodcustprice->lines[0]->recuperableonly;
2341 if (empty($tva_tx)) {
2347 if (!$pricebycustomerexist && !empty($thirdparty_buyer->price_level)) {
2348 $pu_ht = $this->multiprices[$thirdparty_buyer->price_level];
2349 $pu_ttc = $this->multiprices_ttc[$thirdparty_buyer->price_level];
2350 $price_min = $this->multiprices_min[$thirdparty_buyer->price_level];
2351 $price_base_type = $this->multiprices_base_type[$thirdparty_buyer->price_level];
2354 if (isset($this->multiprices_tva_tx[$thirdparty_buyer->price_level])) {
2355 $tva_tx = $this->multiprices_tva_tx[$thirdparty_buyer->price_level];
2357 if (isset($this->multiprices_recuperableonly[$thirdparty_buyer->price_level])) {
2358 $tva_npr = $this->multiprices_recuperableonly[$thirdparty_buyer->price_level];
2360 if (empty($tva_tx)) {
2365 } elseif (
getDolGlobalString(
'PRODUIT_MULTIPRICES') && !empty($thirdparty_buyer->price_level)) {
2366 $pu_ht = $this->multiprices[$thirdparty_buyer->price_level];
2367 $pu_ttc = $this->multiprices_ttc[$thirdparty_buyer->price_level];
2368 $price_min = $this->multiprices_min[$thirdparty_buyer->price_level];
2369 $price_base_type = $this->multiprices_base_type[$thirdparty_buyer->price_level];
2371 if (isset($this->multiprices_tva_tx[$thirdparty_buyer->price_level])) {
2372 $tva_tx = $this->multiprices_tva_tx[$thirdparty_buyer->price_level];
2374 if (isset($this->multiprices_recuperableonly[$thirdparty_buyer->price_level])) {
2375 $tva_npr = $this->multiprices_recuperableonly[$thirdparty_buyer->price_level];
2377 if (empty($tva_tx)) {
2383 require_once DOL_DOCUMENT_ROOT.
'/product/class/productcustomerprice.class.php';
2387 $filter = array(
't.fk_product' => $this->
id,
't.fk_soc' => $thirdparty_buyer->id);
2389 $result = $prodcustprice->fetchAll(
'',
'', 0, 0, $filter);
2391 if (count($prodcustprice->lines) > 0) {
2392 $pu_ht =
price($prodcustprice->lines[0]->price);
2393 $price_min =
price($prodcustprice->lines[0]->price_min);
2394 $pu_ttc =
price($prodcustprice->lines[0]->price_ttc);
2395 $price_base_type = $prodcustprice->lines[0]->price_base_type;
2396 $tva_tx = $prodcustprice->lines[0]->tva_tx;
2397 if ($prodcustprice->lines[0]->default_vat_code && !preg_match(
'/\(.*\)/', $tva_tx)) {
2398 $tva_tx .=
' ('.$prodcustprice->lines[0]->default_vat_code.
')';
2400 $tva_npr = $prodcustprice->lines[0]->recuperableonly;
2401 if (empty($tva_tx)) {
2408 if ($this->prices_by_qty[0]) {
2411 foreach ($this->prices_by_qty_list[0] as $priceforthequantityarray) {
2412 if ($priceforthequantityarray[
'rowid'] != $pqp) {
2416 if ($priceforthequantityarray[
'price_base_type'] ==
'HT') {
2417 $pu_ht = $priceforthequantityarray[
'unitprice'];
2419 $pu_ttc = $priceforthequantityarray[
'unitprice'];
2426 if ($this->prices_by_qty[$thirdparty_buyer->price_level]) {
2429 foreach ($this->prices_by_qty_list[$thirdparty_buyer->price_level] as $priceforthequantityarray) {
2430 if ($priceforthequantityarray[
'rowid'] != $pqp) {
2434 if ($priceforthequantityarray[
'price_base_type'] ==
'HT') {
2435 $pu_ht = $priceforthequantityarray[
'unitprice'];
2437 $pu_ttc = $priceforthequantityarray[
'unitprice'];
2444 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);
2461 public function get_buyprice($prodfournprice, $qty, $product_id = 0, $fourn_ref =
'', $fk_soc = 0)
2464 global $action, $hookmanager;
2467 if (is_object($hookmanager)) {
2468 $parameters = array(
2469 'prodfournprice' => $prodfournprice,
2471 'product_id' => $product_id,
2472 'fourn_ref' => $fourn_ref,
2473 'fk_soc' => $fk_soc,
2476 $reshook = $hookmanager->executeHooks(
'getBuyPrice', $parameters, $this, $action);
2478 return $hookmanager->resArray;
2485 $sql =
"SELECT pfp.rowid, pfp.price as price, pfp.quantity as quantity, pfp.remise_percent, pfp.fk_soc,";
2486 $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,";
2487 $sql .=
" pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code,";
2488 $sql .=
" pfp.packaging";
2489 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price as pfp";
2490 $sql .=
" WHERE pfp.rowid = ".((int) $prodfournprice);
2492 $sql .=
" AND pfp.quantity <= ".((float) $qty);
2494 $sql .=
" ORDER BY pfp.quantity DESC";
2496 dol_syslog(get_class($this).
"::get_buyprice first search by prodfournprice/qty", LOG_DEBUG);
2497 $resql = $this->db->query($sql);
2499 $obj = $this->db->fetch_object($resql);
2500 if ($obj && $obj->quantity > 0) {
2501 if (isModEnabled(
'dynamicprices') && !empty($obj->fk_supplier_price_expression)) {
2503 $prod_supplier->product_fourn_price_id = $obj->rowid;
2504 $prod_supplier->id = $obj->fk_product;
2505 $prod_supplier->fourn_qty = $obj->quantity;
2506 $prod_supplier->fourn_tva_tx = $obj->tva_tx;
2507 $prod_supplier->fk_supplier_price_expression = $obj->fk_supplier_price_expression;
2509 include_once DOL_DOCUMENT_ROOT.
'/product/dynamic_price/class/price_parser.class.php';
2511 $price_result = $priceparser->parseProductSupplier($prod_supplier);
2512 if ($price_result >= 0) {
2513 $obj->price = $price_result;
2516 $this->product_fourn_price_id = $obj->rowid;
2517 $this->buyprice = $obj->price;
2518 $this->fourn_pu = $obj->price / $obj->quantity;
2519 $this->fourn_price_base_type =
'HT';
2520 $this->fourn_socid = $obj->fk_soc;
2521 $this->ref_fourn = $obj->ref_supplier;
2522 $this->ref_supplier = $obj->ref_supplier;
2523 $this->desc_supplier = $obj->desc_supplier;
2524 $this->remise_percent = $obj->remise_percent;
2525 $this->vatrate_supplier = $obj->tva_tx;
2526 $this->default_vat_code_supplier = $obj->default_vat_code;
2527 $this->fourn_multicurrency_price = $obj->multicurrency_price;
2528 $this->fourn_multicurrency_unitprice = $obj->multicurrency_unitprice;
2529 $this->fourn_multicurrency_tx = $obj->multicurrency_tx;
2530 $this->fourn_multicurrency_id = $obj->fk_multicurrency;
2531 $this->fourn_multicurrency_code = $obj->multicurrency_code;
2533 $this->packaging = $obj->packaging;
2535 $result = $obj->fk_product;
2539 $sql =
"SELECT pfp.rowid, pfp.price as price, pfp.quantity as quantity, pfp.remise_percent, pfp.fk_soc,";
2540 $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,";
2541 $sql .=
" pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code,";
2542 $sql .=
" pfp.packaging";
2543 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price as pfp";
2544 $sql .=
" WHERE 1 = 1";
2545 if ($product_id > 0) {
2546 $sql .=
" AND pfp.fk_product = ".((int) $product_id);
2548 if ($fourn_ref !=
'none') {
2549 $sql .=
" AND pfp.ref_fourn = '".$this->db->escape($fourn_ref).
"'";
2552 $sql .=
" AND pfp.fk_soc = ".((int) $fk_soc);
2555 $sql .=
" AND pfp.quantity <= ".((float) $qty);
2557 $sql .=
" ORDER BY pfp.quantity DESC";
2560 dol_syslog(get_class($this).
"::get_buyprice second search from qty/ref/product_id", LOG_DEBUG);
2561 $resql = $this->db->query($sql);
2563 $obj = $this->db->fetch_object($resql);
2564 if ($obj && $obj->quantity > 0) {
2565 if (isModEnabled(
'dynamicprices') && !empty($obj->fk_supplier_price_expression)) {
2567 $prod_supplier->product_fourn_price_id = $obj->rowid;
2568 $prod_supplier->id = $obj->fk_product;
2569 $prod_supplier->fourn_qty = $obj->quantity;
2570 $prod_supplier->fourn_tva_tx = $obj->tva_tx;
2571 $prod_supplier->fk_supplier_price_expression = $obj->fk_supplier_price_expression;
2573 include_once DOL_DOCUMENT_ROOT.
'/product/dynamic_price/class/price_parser.class.php';
2575 $price_result = $priceparser->parseProductSupplier($prod_supplier);
2577 $obj->price = $price_result;
2580 $this->product_fourn_price_id = $obj->rowid;
2581 $this->buyprice = $obj->price;
2582 $this->fourn_qty = $obj->quantity;
2583 $this->fourn_pu = $obj->price / $obj->quantity;
2584 $this->fourn_price_base_type =
'HT';
2585 $this->fourn_socid = $obj->fk_soc;
2586 $this->ref_fourn = $obj->ref_supplier;
2587 $this->ref_supplier = $obj->ref_supplier;
2588 $this->desc_supplier = $obj->desc_supplier;
2589 $this->remise_percent = $obj->remise_percent;
2590 $this->vatrate_supplier = $obj->tva_tx;
2591 $this->default_vat_code_supplier = $obj->default_vat_code;
2592 $this->fourn_multicurrency_price = $obj->multicurrency_price;
2593 $this->fourn_multicurrency_unitprice = $obj->multicurrency_unitprice;
2594 $this->fourn_multicurrency_tx = $obj->multicurrency_tx;
2595 $this->fourn_multicurrency_id = $obj->fk_multicurrency;
2596 $this->fourn_multicurrency_code = $obj->multicurrency_code;
2598 $this->packaging = $obj->packaging;
2600 $result = $obj->fk_product;
2606 $this->error = $this->db->lasterror();
2611 $this->error = $this->db->lasterror();
2635 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)
2641 dol_syslog(get_class($this).
"::update_price id=".$id.
" newprice=".$newprice.
" newpricebase=".$newpricebase.
" newminprice=".$newminprice.
" level=".$level.
" npr=".$newnpr.
" newdefaultvatcode=".$newdefaultvatcode);
2644 if (empty($this->tva_tx)) {
2647 if (empty($newnpr)) {
2650 if (empty($newminprice)) {
2655 if ($newvat ===
null || $newvat ==
'') {
2656 $newvat = $this->tva_tx;
2659 $localtaxtype1 =
'';
2660 $localtaxtype2 =
'';
2665 return $this->
generateMultiprices($user, $newprice, $newpricebase, $newvat, $newnpr, $newpbq);
2668 if (!empty($newminprice) && ($newminprice > $newprice)) {
2669 $this->error =
'ErrorPriceCantBeLowerThanMinPrice';
2673 if ($newprice === 0 || $newprice !==
'') {
2674 if ($newpricebase ==
'TTC') {
2675 $price_ttc =
price2num($newprice,
'MU');
2676 $price = (float)
price2num($newprice) / (1 + ((float) $newvat / 100));
2679 if ($newminprice !=
'' || $newminprice == 0) {
2680 $price_min_ttc =
price2num($newminprice,
'MU');
2681 $price_min = (float)
price2num($newminprice) / (1 + ($newvat / 100));
2682 $price_min =
price2num($price_min,
'MU');
2688 $price = (float)
price2num($newprice,
'MU');
2689 $price_ttc = ($newnpr != 1) ? (
float)
price2num($newprice) * (1 + ($newvat / 100)) : $price;
2690 $price_ttc = (float)
price2num($price_ttc,
'MU');
2692 if ($newminprice !==
'' || $newminprice == 0) {
2693 $price_min =
price2num($newminprice,
'MU');
2694 $price_min_ttc = (float)
price2num($newminprice) * (1 + ($newvat / 100));
2695 $price_min_ttc =
price2num($price_min_ttc,
'MU');
2703 if (count($localtaxes_array) > 0) {
2704 $localtaxtype1 = $localtaxes_array[
'0'];
2705 $localtax1 = $localtaxes_array[
'1'];
2706 $localtaxtype2 = $localtaxes_array[
'2'];
2707 $localtax2 = $localtaxes_array[
'3'];
2710 if (!empty($newdefaultvatcode)) {
2713 $sql =
"SELECT t.rowid, t.code, t.recuperableonly as tva_npr, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
2714 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_tva as t, ".MAIN_DB_PREFIX.
"c_country as c";
2715 $sql .=
" WHERE t.fk_pays = c.rowid AND c.code = '".$this->db->escape($mysoc->country_code).
"'";
2716 $sql .=
" AND t.taux = ".((float) $newdefaultvatcode).
" AND t.active = 1";
2717 $sql .=
" AND t.code = '".$this->db->escape($newdefaultvatcode).
"'";
2718 $resql = $this->db->query($sql);
2720 $obj = $this->db->fetch_object($resql);
2722 $npr = $obj->tva_npr;
2723 $localtax1 = $obj->localtax1;
2724 $localtax2 = $obj->localtax2;
2725 $localtaxtype1 = $obj->localtax1_type;
2726 $localtaxtype2 = $obj->localtax2_type;
2731 $localtaxtype1 =
'0';
2733 $localtaxtype2 =
'0';
2737 if (empty($localtax1)) {
2740 if (empty($localtax2)) {
2748 $sql =
"UPDATE ".$this->db->prefix().
"product SET";
2749 $sql .=
" price_base_type = '".$this->db->escape($newpricebase).
"',";
2750 $sql .=
" price = ".(float) $price.
",";
2751 $sql .=
" price_ttc = ".(float) $price_ttc.
",";
2752 $sql .=
" price_min = ".(float) $price_min.
",";
2753 $sql .=
" price_min_ttc = ".(float) $price_min_ttc.
",";
2754 $sql .=
" localtax1_tx = ".($localtax1 >= 0 ? (float) $localtax1 :
'NULL').
",";
2755 $sql .=
" localtax2_tx = ".($localtax2 >= 0 ? (float) $localtax2 :
'NULL').
",";
2756 $sql .=
" localtax1_type = ".($localtaxtype1 !=
'' ?
"'".$this->db->escape($localtaxtype1).
"'" :
"'0'").
",";
2757 $sql .=
" localtax2_type = ".($localtaxtype2 !=
'' ?
"'".$this->db->escape($localtaxtype2).
"'" :
"'0'").
",";
2758 $sql .=
" default_vat_code = ".($newdefaultvatcode ?
"'".$this->db->escape($newdefaultvatcode).
"'" :
"null").
",";
2759 $sql .=
" price_label = ".(!empty($price_label) ?
"'".$this->db->escape($price_label).
"'" :
"null").
",";
2760 $sql .=
" tva_tx = ".(float)
price2num($newvat).
",";
2761 $sql .=
" recuperableonly = '".$this->db->escape($newnpr).
"'";
2762 $sql .=
" WHERE rowid = ".((int) $id);
2764 dol_syslog(get_class($this).
"::update_price", LOG_DEBUG);
2765 $resql = $this->db->query($sql);
2767 $this->multiprices[$level] = $price;
2768 $this->multiprices_ttc[$level] = $price_ttc;
2769 $this->multiprices_min[$level] = $price_min;
2770 $this->multiprices_min_ttc[$level] = $price_min_ttc;
2771 $this->multiprices_base_type[$level] = $newpricebase;
2772 $this->multiprices_default_vat_code[$level] = $newdefaultvatcode;
2773 $this->multiprices_tva_tx[$level] = $newvat;
2774 $this->multiprices_recuperableonly[$level] = $newnpr;
2776 $this->
price = $price;
2777 $this->price_label = $price_label;
2778 $this->price_ttc = $price_ttc;
2779 $this->price_min = $price_min;
2780 $this->price_min_ttc = $price_min_ttc;
2781 $this->price_base_type = $newpricebase;
2782 $this->default_vat_code = $newdefaultvatcode;
2783 $this->tva_tx = $newvat;
2784 $this->tva_npr = $newnpr;
2787 $this->localtax1_tx = $localtax1;
2788 $this->localtax2_tx = $localtax2;
2789 $this->localtax1_type = $localtaxtype1;
2790 $this->localtax2_type = $localtaxtype2;
2793 $this->price_by_qty = $newpbq;
2797 if (!empty(array_diff_assoc($newPriceData, $lastPriceData)) || !
getDolGlobalString(
'PRODUIT_MULTIPRICES')) {
2801 $this->level = $level;
2805 $result = $this->
call_trigger(
'PRODUCT_PRICE_MODIFY', $user);
2807 $this->db->rollback();
2813 $this->db->commit();
2815 $this->db->rollback();
2816 $this->error = $this->db->lasterror();
2835 $this->fk_price_expression = $expression_id;
2837 return $this->
update($this->
id, $user);
2852 public function fetch($id = 0, $ref =
'', $ref_ext =
'', $barcode =
'', $ignore_expression = 0, $ignore_price_load = 0, $ignore_lang_load = 0)
2854 include_once DOL_DOCUMENT_ROOT.
'/core/lib/company.lib.php';
2858 dol_syslog(get_class($this).
"::fetch id=".$id.
" ref=".$ref.
" ref_ext=".$ref_ext);
2861 if (!$id && !$ref && !$ref_ext && !$barcode) {
2862 $this->error =
'ErrorWrongParameters';
2863 dol_syslog(get_class($this).
"::fetch ".$this->error, LOG_ERR);
2867 $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,";
2868 $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,";
2869 $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,";
2870 $sql .=
" p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.last_main_doc,";
2871 $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,";
2873 $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,";
2875 $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,";
2880 $separatedEntityPMP =
false;
2881 $separatedStock =
false;
2882 $visibleWarehousesEntities = $conf->entity;
2885 $checkPMPPerEntity = $this->db->query(
"SELECT pmp FROM " . $this->db->prefix() .
"product_perentity WHERE fk_product = ".((int) $id).
" AND entity = ".(
int) $conf->entity);
2886 if ($this->db->num_rows($checkPMPPerEntity) > 0) {
2887 $separatedEntityPMP =
true;
2891 $separatedStock =
true;
2892 if (isset($mc->sharings[
'stock']) && !empty($mc->sharings[
'stock'])) {
2893 $visibleWarehousesEntities .=
"," . implode(
",", $mc->sharings[
'stock']);
2896 if ($separatedEntityPMP) {
2897 $sql .=
" ppe.pmp,";
2901 $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,";
2902 $sql .=
" p.fk_price_expression, p.price_autogen, p.model_pdf,";
2903 $sql .=
" p.price_label,";
2904 if ($separatedStock) {
2905 $sql .=
" SUM(sp.reel) as stock";
2909 $sql .=
" FROM ".$this->db->prefix().
"product as p";
2911 $sql .=
" LEFT JOIN " . $this->db->prefix() .
"product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity);
2913 if ($separatedStock) {
2914 $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).
"))";
2918 $sql .=
" WHERE p.rowid = ".((int) $id);
2920 $sql .=
" WHERE p.entity IN (".getEntity($this->element).
")";
2922 $sql .=
" AND p.ref = '".$this->db->escape($ref).
"'";
2923 } elseif ($ref_ext) {
2924 $sql .=
" AND p.ref_ext = '".$this->db->escape($ref_ext).
"'";
2925 } elseif ($barcode) {
2926 $sql .=
" AND p.barcode = '".$this->db->escape($barcode).
"'";
2929 if ($separatedStock) {
2930 $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,";
2931 $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,";
2932 $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,";
2933 $sql .=
" p.length, p.length_units, p.width, p.width_units, p.height, p.height_units,";
2934 $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,";
2936 $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,";
2938 $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,";
2940 if ($separatedEntityPMP) {
2941 $sql .=
" ppe.pmp,";
2945 $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,";
2946 $sql .=
" p.fk_price_expression, p.price_autogen, p.model_pdf";
2947 $sql .=
" ,p.price_label";
2948 if (!$separatedStock) {
2949 $sql .=
", p.stock";
2953 $resql = $this->db->query($sql);
2955 unset($this->oldcopy);
2957 if ($this->db->num_rows($resql) > 0) {
2958 $obj = $this->db->fetch_object($resql);
2960 $this->
id = $obj->rowid;
2961 $this->
ref = $obj->ref;
2962 $this->ref_ext = $obj->ref_ext;
2963 $this->label = $obj->label;
2965 $this->url = $obj->url;
2966 $this->note_public = $obj->note_public;
2967 $this->note_private = $obj->note_private;
2968 $this->note = $obj->note_private;
2970 $this->
type = $obj->fk_product_type;
2971 $this->price_label = $obj->price_label;
2972 $this->
status = $obj->tosell;
2973 $this->status_buy = $obj->tobuy;
2974 $this->status_batch = $obj->tobatch;
2975 $this->sell_or_eat_by_mandatory = $obj->sell_or_eat_by_mandatory;
2976 $this->batch_mask = $obj->batch_mask;
2978 $this->customcode = $obj->customcode;
2979 $this->country_id = $obj->fk_country;
2980 $this->country_code =
getCountry($this->country_id,
'2', $this->db);
2981 $this->state_id = $obj->fk_state;
2982 $this->lifetime = $obj->lifetime;
2983 $this->qc_frequency = $obj->qc_frequency;
2984 $this->
price = $obj->price;
2985 $this->price_ttc = $obj->price_ttc;
2986 $this->price_min = $obj->price_min;
2987 $this->price_min_ttc = $obj->price_min_ttc;
2988 $this->price_base_type = $obj->price_base_type;
2989 $this->cost_price = $obj->cost_price;
2990 $this->default_vat_code = $obj->default_vat_code;
2991 $this->tva_tx = $obj->tva_tx;
2993 $this->tva_npr = $obj->tva_npr;
2995 $this->localtax1_tx = $obj->localtax1_tx;
2996 $this->localtax2_tx = $obj->localtax2_tx;
2997 $this->localtax1_type = $obj->localtax1_type;
2998 $this->localtax2_type = $obj->localtax2_type;
3000 $this->finished = $obj->finished;
3001 $this->fk_default_bom = $obj->fk_default_bom;
3003 $this->duration = $obj->duration;
3005 preg_match(
'/(\d+)(\w+)/', $obj->duration, $matches);
3006 $this->duration_value = !empty($matches[1]) ? (int) $matches[1] : 0;
3007 $this->duration_unit = !empty($matches[2]) ? (string) $matches[2] :
null;
3008 $this->canvas = $obj->canvas;
3009 $this->net_measure = $obj->net_measure;
3010 $this->net_measure_units = $obj->net_measure_units;
3011 $this->weight = $obj->weight;
3012 $this->weight_units = $obj->weight_units;
3013 $this->length = $obj->length;
3014 $this->length_units = $obj->length_units;
3015 $this->width = $obj->width;
3016 $this->width_units = $obj->width_units;
3017 $this->height = $obj->height;
3018 $this->height_units = $obj->height_units;
3020 $this->surface = $obj->surface;
3021 $this->surface_units = $obj->surface_units;
3022 $this->volume = $obj->volume;
3023 $this->volume_units = $obj->volume_units;
3024 $this->barcode = $obj->barcode;
3025 $this->barcode_type = $obj->fk_barcode_type;
3027 $this->accountancy_code_buy = $obj->accountancy_code_buy;
3028 $this->accountancy_code_buy_intra = $obj->accountancy_code_buy_intra;
3029 $this->accountancy_code_buy_export = $obj->accountancy_code_buy_export;
3030 $this->accountancy_code_sell = $obj->accountancy_code_sell;
3031 $this->accountancy_code_sell_intra = $obj->accountancy_code_sell_intra;
3032 $this->accountancy_code_sell_export = $obj->accountancy_code_sell_export;
3034 $this->fk_default_warehouse = $obj->fk_default_warehouse;
3035 $this->fk_default_workstation = $obj->fk_default_workstation;
3036 $this->seuil_stock_alerte = $obj->seuil_stock_alerte;
3037 $this->desiredstock = $obj->desiredstock;
3038 $this->stock_reel = $obj->stock;
3039 $this->pmp = $obj->pmp;
3041 $this->date_creation = $obj->datec;
3042 $this->date_modification = $obj->tms;
3043 $this->import_key = $obj->import_key;
3044 $this->entity = $obj->entity;
3046 $this->ref_ext = $obj->ref_ext;
3047 $this->fk_price_expression = $obj->fk_price_expression;
3048 $this->fk_unit = $obj->fk_unit;
3049 $this->price_autogen = $obj->price_autogen;
3050 $this->model_pdf = $obj->model_pdf;
3051 $this->last_main_doc = $obj->last_main_doc;
3053 $this->mandatory_period = $obj->mandatory_period;
3055 $this->db->free($resql);
3068 for ($i = 1; $i <= $produit_multiprices_limit; $i++) {
3069 $sql =
"SELECT price, price_ttc, price_min, price_min_ttc,";
3070 $sql .=
" price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid, recuperableonly";
3071 $sql .=
" ,price_label";
3072 $sql .=
" FROM ".$this->db->prefix().
"product_price";
3073 $sql .=
" WHERE entity IN (".getEntity(
'productprice').
")";
3074 $sql .=
" AND price_level=".((int) $i);
3075 $sql .=
" AND fk_product = ".((int) $this->
id);
3076 $sql .=
" ORDER BY date_price DESC, rowid DESC";
3078 $resql = $this->db->query($sql);
3080 $result = $this->db->fetch_array($resql);
3082 $this->multiprices[$i] = $result ? $result[
"price"] :
null;
3083 $this->multiprices_ttc[$i] = $result ? $result[
"price_ttc"] :
null;
3084 $this->multiprices_min[$i] = $result ? $result[
"price_min"] :
null;
3085 $this->multiprices_min_ttc[$i] = $result ? $result[
"price_min_ttc"] :
null;
3086 $this->multiprices_base_type[$i] = $result ? $result[
"price_base_type"] :
null;
3088 $this->multiprices_tva_tx[$i] = $result ? $result[
"tva_tx"].($result ?
' ('.$result[
'default_vat_code'].
')' :
'') :
null;
3089 $this->multiprices_recuperableonly[$i] = $result ? $result[
"recuperableonly"] :
null;
3128 $this->error = $this->db->lasterror;
3134 } elseif (
getDolGlobalString(
'PRODUIT_CUSTOMER_PRICES_BY_QTY') && empty($ignore_price_load)) {
3135 $sql =
"SELECT price, price_ttc, price_min, price_min_ttc,";
3136 $sql .=
" price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid";
3137 $sql .=
" FROM ".$this->db->prefix().
"product_price";
3138 $sql .=
" WHERE fk_product = ".((int) $this->
id);
3139 $sql .=
" ORDER BY date_price DESC, rowid DESC";
3142 $resql = $this->db->query($sql);
3144 $result = $this->db->fetch_array($resql);
3148 $this->prices_by_qty[0] = $result[
"price_by_qty"];
3149 $this->prices_by_qty_id[0] = $result[
"rowid"];
3151 if ($this->prices_by_qty[0] == 1) {
3152 $sql =
"SELECT rowid,price, unitprice, quantity, remise_percent, remise, remise, price_base_type";
3153 $sql .=
" FROM ".$this->db->prefix().
"product_price_by_qty";
3154 $sql .=
" WHERE fk_product_price = ".((int) $this->prices_by_qty_id[0]);
3155 $sql .=
" ORDER BY quantity ASC";
3157 $resql = $this->db->query($sql);
3159 $resultat = array();
3161 while ($result = $this->db->fetch_array($resql)) {
3162 $resultat[$ii] = array();
3163 $resultat[$ii][
"rowid"] = $result[
"rowid"];
3164 $resultat[$ii][
"price"] = $result[
"price"];
3165 $resultat[$ii][
"unitprice"] = $result[
"unitprice"];
3166 $resultat[$ii][
"quantity"] = $result[
"quantity"];
3167 $resultat[$ii][
"remise_percent"] = $result[
"remise_percent"];
3169 $resultat[$ii][
"price_base_type"] = $result[
"price_base_type"];
3172 $this->prices_by_qty_list[0] = $resultat;
3174 $this->error = $this->db->lasterror;
3180 $this->error = $this->db->lasterror;
3183 } elseif (
getDolGlobalString(
'PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') && empty($ignore_price_load)) {
3185 for ($i = 1; $i <= $produit_multiprices_limit; $i++) {
3186 $sql =
"SELECT price, price_ttc, price_min, price_min_ttc,";
3187 $sql .=
" price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid, recuperableonly";
3188 $sql .=
" FROM ".$this->db->prefix().
"product_price";
3189 $sql .=
" WHERE entity IN (".getEntity(
'productprice').
")";
3190 $sql .=
" AND price_level=".((int) $i);
3191 $sql .=
" AND fk_product = ".((int) $this->
id);
3192 $sql .=
" ORDER BY date_price DESC, rowid DESC";
3194 $resql = $this->db->query($sql);
3196 $this->error = $this->db->lasterror;
3198 } elseif ($result = $this->db->fetch_array($resql)) {
3199 $this->multiprices[$i] = (!empty($result[
"price"]) ? $result[
"price"] : 0);
3200 $this->multiprices_ttc[$i] = (!empty($result[
"price_ttc"]) ? $result[
"price_ttc"] : 0);
3201 $this->multiprices_min[$i] = (!empty($result[
"price_min"]) ? $result[
"price_min"] : 0);
3202 $this->multiprices_min_ttc[$i] = (!empty($result[
"price_min_ttc"]) ? $result[
"price_min_ttc"] : 0);
3203 $this->multiprices_base_type[$i] = (!empty($result[
"price_base_type"]) ? $result[
"price_base_type"] :
'');
3205 $this->multiprices_tva_tx[$i] = (!empty($result[
"tva_tx"]) ? $result[
"tva_tx"] : 0);
3206 $this->multiprices_recuperableonly[$i] = (!empty($result[
"recuperableonly"]) ? $result[
"recuperableonly"] : 0);
3209 $this->prices_by_qty[$i] = (!empty($result[
"price_by_qty"]) ? $result[
"price_by_qty"] : 0);
3210 $this->prices_by_qty_id[$i] = (!empty($result[
"rowid"]) ? $result[
"rowid"] : 0);
3212 if ($this->prices_by_qty[$i] == 1) {
3213 $sql =
"SELECT rowid, price, unitprice, quantity, remise_percent, remise, price_base_type";
3214 $sql .=
" FROM ".$this->db->prefix().
"product_price_by_qty";
3215 $sql .=
" WHERE fk_product_price = ".((int) $this->prices_by_qty_id[$i]);
3216 $sql .=
" ORDER BY quantity ASC";
3218 $resql = $this->db->query($sql);
3220 $resultat = array();
3222 while ($result = $this->db->fetch_array($resql)) {
3223 $resultat[$ii] = array();
3224 $resultat[$ii][
"rowid"] = $result[
"rowid"];
3225 $resultat[$ii][
"price"] = $result[
"price"];
3226 $resultat[$ii][
"unitprice"] = $result[
"unitprice"];
3227 $resultat[$ii][
"quantity"] = $result[
"quantity"];
3228 $resultat[$ii][
"remise_percent"] = $result[
"remise_percent"];
3229 $resultat[$ii][
"remise"] = $result[
"remise"];
3230 $resultat[$ii][
"price_base_type"] = $result[
"price_base_type"];
3233 $this->prices_by_qty_list[$i] = $resultat;
3235 $this->error = $this->db->lasterror;
3243 if (isModEnabled(
'dynamicprices') && !empty($this->fk_price_expression) && empty($ignore_expression)) {
3244 include_once DOL_DOCUMENT_ROOT.
'/product/dynamic_price/class/price_parser.class.php';
3246 $price_result = $priceparser->parseProduct($this);
3247 if ($price_result >= 0) {
3248 $this->
price = $price_result;
3250 $this->price_ttc = (float)
price2num($this->
price) * (1 + ($this->tva_tx / 100));
3251 $this->price_ttc = (float)
price2num($this->price_ttc,
'MU');
3257 $this->stock_warehouse = array();
3264 $this->error = $this->db->lasterror();
3279 global $user, $hookmanager, $action;
3283 foreach (array(
'toconsume',
'consumed',
'toproduce',
'produced') as $role) {
3284 $this->stats_mo[
'customers_'.$role] = 0;
3285 $this->stats_mo[
'nb_'.$role] = 0;
3286 $this->stats_mo[
'qty_'.$role] = 0;
3288 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,";
3289 $sql .=
" SUM(mp.qty) as qty";
3290 $sql .=
" FROM ".$this->db->prefix().
"mrp_mo as c";
3291 $sql .=
" INNER JOIN ".$this->db->prefix().
"mrp_production as mp ON mp.fk_mo=c.rowid";
3292 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3293 $sql .=
" INNER JOIN ".$this->db->prefix().
"societe_commerciaux as sc ON sc.fk_soc=c.fk_soc AND sc.fk_user = ".((int) $user->id);
3296 $sql .=
" c.entity IN (".getEntity(
'mo').
")";
3298 $sql .=
" AND mp.fk_product = ".((int) $this->
id);
3299 $sql .=
" AND mp.role ='".$this->db->escape($role).
"'";
3301 $sql .=
" AND c.fk_soc = ".((int) $socid);
3304 $result = $this->db->query($sql);
3306 $obj = $this->db->fetch_object($result);
3307 $this->stats_mo[
'customers_'.$role] = $obj->nb_customers ? $obj->nb_customers : 0;
3308 $this->stats_mo[
'nb_'.$role] = $obj->nb ? $obj->nb : 0;
3309 $this->stats_mo[
'qty_'.$role] = $obj->qty ?
price2num($obj->qty,
'MS') : 0;
3311 $this->error = $this->db->error();
3316 if (!empty($error)) {
3320 $parameters = array(
'socid' => $socid);
3321 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerMO', $parameters, $this, $action);
3323 $this->stats_mo = $hookmanager->resArray[
'stats_mo'];
3339 global $hookmanager, $action;
3343 $this->stats_bom[
'nb_toproduce'] = 0;
3344 $this->stats_bom[
'nb_toconsume'] = 0;
3345 $this->stats_bom[
'qty_toproduce'] = 0;
3346 $this->stats_bom[
'qty_toconsume'] = 0;
3348 $sql =
"SELECT COUNT(DISTINCT b.rowid) as nb_toproduce,";
3349 $sql .=
" SUM(b.qty) as qty_toproduce";
3350 $sql .=
" FROM ".$this->db->prefix().
"bom_bom as b";
3351 $sql .=
" INNER JOIN ".$this->db->prefix().
"bom_bomline as bl ON bl.fk_bom=b.rowid";
3353 $sql .=
" b.entity IN (".getEntity(
'bom').
")";
3354 $sql .=
" AND b.fk_product =".((int) $this->
id);
3355 $sql .=
" GROUP BY b.rowid";
3357 $result = $this->db->query($sql);
3359 $obj = $this->db->fetch_object($result);
3360 $this->stats_bom[
'nb_toproduce'] = !empty($obj->nb_toproduce) ? $obj->nb_toproduce : 0;
3361 $this->stats_bom[
'qty_toproduce'] = !empty($obj->qty_toproduce) ?
price2num($obj->qty_toproduce) : 0;
3363 $this->error = $this->db->error();
3367 $sql =
"SELECT COUNT(DISTINCT bl.rowid) as nb_toconsume,";
3368 $sql .=
" SUM(bl.qty) as qty_toconsume";
3369 $sql .=
" FROM ".$this->db->prefix().
"bom_bom as b";
3370 $sql .=
" INNER JOIN ".$this->db->prefix().
"bom_bomline as bl ON bl.fk_bom=b.rowid";
3372 $sql .=
" b.entity IN (".getEntity(
'bom').
")";
3373 $sql .=
" AND bl.fk_product =".((int) $this->
id);
3375 $result = $this->db->query($sql);
3377 $obj = $this->db->fetch_object($result);
3378 $this->stats_bom[
'nb_toconsume'] = !empty($obj->nb_toconsume) ? $obj->nb_toconsume : 0;
3379 $this->stats_bom[
'qty_toconsume'] = !empty($obj->qty_toconsume) ?
price2num($obj->qty_toconsume) : 0;
3381 $this->error = $this->db->error();
3385 if (!empty($error)) {
3389 $parameters = array(
'socid' => $socid);
3390 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerMO', $parameters, $this, $action);
3392 $this->stats_bom = $hookmanager->resArray[
'stats_bom'];
3408 global $user, $hookmanager, $action;
3410 $sql =
"SELECT COUNT(DISTINCT p.fk_soc) as nb_customers, COUNT(DISTINCT p.rowid) as nb,";
3411 $sql .=
" COUNT(pd.rowid) as nb_rows, SUM(pd.qty) as qty";
3412 $sql .=
" FROM ".$this->db->prefix().
"propaldet as pd";
3413 $sql .=
", ".$this->db->prefix().
"propal as p";
3414 $sql .=
", ".$this->db->prefix().
"societe as s";
3415 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3416 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3418 $sql .=
" WHERE p.rowid = pd.fk_propal";
3419 $sql .=
" AND p.fk_soc = s.rowid";
3420 $sql .=
" AND p.entity IN (".getEntity(
'propal').
")";
3421 $sql .=
" AND pd.fk_product = ".((int) $this->
id);
3422 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3423 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3427 $sql .=
" AND p.fk_soc = ".((int) $socid);
3430 $result = $this->db->query($sql);
3432 $obj = $this->db->fetch_object($result);
3433 $this->stats_propale[
'customers'] = $obj->nb_customers;
3434 $this->stats_propale[
'nb'] = $obj->nb;
3435 $this->stats_propale[
'rows'] = $obj->nb_rows;
3436 $this->stats_propale[
'qty'] = $obj->qty ? $obj->qty : 0;
3441 if (is_array($TFather) && !empty($TFather)) {
3442 foreach ($TFather as &$fatherData) {
3443 $pFather =
new Product($this->db);
3444 $pFather->id = $fatherData[
'id'];
3445 $qtyCoef = $fatherData[
'qty'];
3447 if ($fatherData[
'incdec']) {
3448 $pFather->load_stats_propale($socid);
3450 $this->stats_propale[
'customers'] += $pFather->stats_propale[
'customers'];
3451 $this->stats_propale[
'nb'] += $pFather->stats_propale[
'nb'];
3452 $this->stats_propale[
'rows'] += $pFather->stats_propale[
'rows'];
3453 $this->stats_propale[
'qty'] += $pFather->stats_propale[
'qty'] * $qtyCoef;
3459 $parameters = array(
'socid' => $socid);
3460 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerProposal', $parameters, $this, $action);
3462 $this->stats_propale = $hookmanager->resArray[
'stats_propale'];
3467 $this->error = $this->db->error();
3483 global $user, $hookmanager, $action;
3485 $sql =
"SELECT COUNT(DISTINCT p.fk_soc) as nb_suppliers, COUNT(DISTINCT p.rowid) as nb,";
3486 $sql .=
" COUNT(pd.rowid) as nb_rows, SUM(pd.qty) as qty";
3487 $sql .=
" FROM ".$this->db->prefix().
"supplier_proposaldet as pd";
3488 $sql .=
", ".$this->db->prefix().
"supplier_proposal as p";
3489 $sql .=
", ".$this->db->prefix().
"societe as s";
3490 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3491 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3493 $sql .=
" WHERE p.rowid = pd.fk_supplier_proposal";
3494 $sql .=
" AND p.fk_soc = s.rowid";
3495 $sql .=
" AND p.entity IN (".getEntity(
'supplier_proposal').
")";
3496 $sql .=
" AND pd.fk_product = ".((int) $this->
id);
3497 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3498 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3502 $sql .=
" AND p.fk_soc = ".((int) $socid);
3505 $result = $this->db->query($sql);
3507 $obj = $this->db->fetch_object($result);
3508 $this->stats_proposal_supplier[
'suppliers'] = $obj->nb_suppliers;
3509 $this->stats_proposal_supplier[
'nb'] = $obj->nb;
3510 $this->stats_proposal_supplier[
'rows'] = $obj->nb_rows;
3511 $this->stats_proposal_supplier[
'qty'] = $obj->qty ? $obj->qty : 0;
3513 $parameters = array(
'socid' => $socid);
3514 $reshook = $hookmanager->executeHooks(
'loadStatsSupplierProposal', $parameters, $this, $action);
3516 $this->stats_proposal_supplier = $hookmanager->resArray[
'stats_proposal_supplier'];
3521 $this->error = $this->db->error();
3539 global $user, $hookmanager, $action;
3541 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,";
3542 $sql .=
" COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty";
3543 $sql .=
" FROM ".$this->db->prefix().
"commandedet as cd";
3544 $sql .=
", ".$this->db->prefix().
"commande as c";
3545 $sql .=
", ".$this->db->prefix().
"societe as s";
3546 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3547 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3549 $sql .=
" WHERE c.rowid = cd.fk_commande";
3550 $sql .=
" AND c.fk_soc = s.rowid";
3551 $sql .=
" AND c.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'commande').
")";
3552 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
3553 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3554 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3557 $sql .=
" AND c.fk_soc = ".((int) $socid);
3559 if ($filtrestatut !=
'') {
3560 $sql .=
" AND c.fk_statut in (".$this->db->sanitize($filtrestatut).
")";
3563 $result = $this->db->query($sql);
3565 $obj = $this->db->fetch_object($result);
3566 $this->stats_commande[
'customers'] = $obj->nb_customers;
3567 $this->stats_commande[
'nb'] = $obj->nb;
3568 $this->stats_commande[
'rows'] = $obj->nb_rows;
3569 $this->stats_commande[
'qty'] = $obj->qty ? $obj->qty : 0;
3574 if (is_array($TFather) && !empty($TFather)) {
3575 foreach ($TFather as &$fatherData) {
3576 $pFather =
new Product($this->db);
3577 $pFather->id = $fatherData[
'id'];
3578 $qtyCoef = $fatherData[
'qty'];
3580 if ($fatherData[
'incdec']) {
3581 $pFather->load_stats_commande($socid, $filtrestatut);
3583 $this->stats_commande[
'customers'] += $pFather->stats_commande[
'customers'];
3584 $this->stats_commande[
'nb'] += $pFather->stats_commande[
'nb'];
3585 $this->stats_commande[
'rows'] += $pFather->stats_commande[
'rows'];
3586 $this->stats_commande[
'qty'] += $pFather->stats_commande[
'qty'] * $qtyCoef;
3598 $sql =
"SELECT SUM(".$this->db->ifsql(
'f.type=2', -1, 1).
" * fd.qty) as count FROM ".$this->db->prefix().
"facturedet as fd ";
3599 $sql .=
" JOIN ".$this->db->prefix().
"facture as f ON fd.fk_facture = f.rowid";
3600 $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'))";
3601 $sql .=
" JOIN ".$this->db->prefix().
"commande as c ON el.fk_source = c.rowid";
3602 $sql .=
" WHERE c.fk_statut IN (".$this->db->sanitize($filtrestatut).
") AND c.facture = 0 AND fd.fk_product = ".((int) $this->
id);
3604 dol_syslog(__METHOD__.
":: sql $sql", LOG_NOTICE);
3605 $resql = $this->db->query($sql);
3607 if ($this->db->num_rows($resql) > 0) {
3608 $obj = $this->db->fetch_object($resql);
3609 $adeduire += $obj->count;
3613 $this->stats_commande[
'qty'] -= $adeduire;
3616 include_once DOL_DOCUMENT_ROOT.
'/compta/facture/class/facture.class.php';
3620 $sql =
"SELECT sum(".$this->db->ifsql(
'f.type=2', -1, 1).
" * fd.qty) as count FROM ".MAIN_DB_PREFIX.
"facturedet as fd ";
3621 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"facture as f ON fd.fk_facture = f.rowid";
3622 $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'))";
3623 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"commande as c ON el.fk_source = c.rowid";
3624 $sql .=
" WHERE c.fk_statut IN (".$this->db->sanitize($filtrestatut).
") AND f.fk_statut > ".
Facture::STATUS_DRAFT.
" AND fd.fk_product = ".((int) $this->
id);
3626 dol_syslog(__METHOD__.
":: sql $sql", LOG_NOTICE);
3627 $resql = $this->db->query($sql);
3629 if ($this->db->num_rows($resql) > 0) {
3630 $obj = $this->db->fetch_object($resql);
3631 $adeduire += $obj->count;
3634 $this->error = $this->db->error();
3638 $this->stats_commande[
'qty'] -= $adeduire;
3642 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3643 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerOrder', $parameters, $this, $action);
3645 $this->stats_commande = $hookmanager->resArray[
'stats_commande'];
3649 $this->error = $this->db->error();
3667 global $user, $hookmanager, $action;
3669 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_suppliers, COUNT(DISTINCT c.rowid) as nb,";
3670 $sql .=
" COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty";
3671 $sql .=
" FROM ".$this->db->prefix().
"commande_fournisseurdet as cd";
3672 $sql .=
", ".$this->db->prefix().
"commande_fournisseur as c";
3673 $sql .=
", ".$this->db->prefix().
"societe as s";
3674 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3675 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3677 $sql .=
" WHERE c.rowid = cd.fk_commande";
3678 $sql .=
" AND c.fk_soc = s.rowid";
3679 $sql .=
" AND c.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'supplier_order').
")";
3680 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
3681 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3682 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3685 $sql .=
" AND c.fk_soc = ".((int) $socid);
3687 if ($filtrestatut !=
'') {
3688 $sql .=
" AND c.fk_statut in (".$this->db->sanitize($filtrestatut).
")";
3690 if (!empty($dateofvirtualstock)) {
3691 $sql .=
" AND c.date_livraison <= '".$this->db->idate($dateofvirtualstock).
"'";
3694 $result = $this->db->query($sql);
3696 $obj = $this->db->fetch_object($result);
3697 $this->stats_commande_fournisseur[
'suppliers'] = $obj->nb_suppliers;
3698 $this->stats_commande_fournisseur[
'nb'] = $obj->nb;
3699 $this->stats_commande_fournisseur[
'rows'] = $obj->nb_rows;
3700 $this->stats_commande_fournisseur[
'qty'] = $obj->qty ? $obj->qty : 0;
3702 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3703 $reshook = $hookmanager->executeHooks(
'loadStatsSupplierOrder', $parameters, $this, $action);
3705 $this->stats_commande_fournisseur = $hookmanager->resArray[
'stats_commande_fournisseur'];
3710 $this->error = $this->db->error().
' sql='.$sql;
3725 public function load_stats_sending($socid = 0, $filtrestatut =
'', $forVirtualStock = 0, $filterShipmentStatus =
'')
3728 global $user, $hookmanager, $action;
3730 $sql =
"SELECT COUNT(DISTINCT e.fk_soc) as nb_customers, COUNT(DISTINCT e.rowid) as nb,";
3731 $sql .=
" COUNT(ed.rowid) as nb_rows, SUM(ed.qty) as qty";
3732 $sql .=
" FROM ".$this->db->prefix().
"expeditiondet as ed";
3733 $sql .=
", ".$this->db->prefix().
"commandedet as cd";
3734 $sql .=
", ".$this->db->prefix().
"commande as c";
3735 $sql .=
", ".$this->db->prefix().
"expedition as e";
3736 $sql .=
", ".$this->db->prefix().
"societe as s";
3737 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3738 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3740 $sql .=
" WHERE e.rowid = ed.fk_expedition";
3741 $sql .=
" AND c.rowid = cd.fk_commande";
3742 $sql .=
" AND e.fk_soc = s.rowid";
3743 $sql .=
" AND e.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'expedition').
")";
3744 $sql .=
" AND ed.fk_elementdet = cd.rowid";
3745 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
3746 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3747 $sql .=
" AND e.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3750 $sql .=
" AND e.fk_soc = ".((int) $socid);
3752 if ($filtrestatut !=
'') {
3753 $sql .=
" AND c.fk_statut IN (".$this->db->sanitize($filtrestatut).
")";
3755 if (!empty($filterShipmentStatus)) {
3756 $sql .=
" AND e.fk_statut IN (".$this->db->sanitize($filterShipmentStatus).
")";
3759 $result = $this->db->query($sql);
3761 $obj = $this->db->fetch_object($result);
3762 $this->stats_expedition[
'customers'] = $obj->nb_customers;
3763 $this->stats_expedition[
'nb'] = $obj->nb;
3764 $this->stats_expedition[
'rows'] = $obj->nb_rows;
3765 $this->stats_expedition[
'qty'] = $obj->qty ? $obj->qty : 0;
3770 if (is_array($TFather) && !empty($TFather)) {
3771 foreach ($TFather as &$fatherData) {
3772 $pFather =
new Product($this->db);
3773 $pFather->id = $fatherData[
'id'];
3774 $qtyCoef = $fatherData[
'qty'];
3776 if ($fatherData[
'incdec']) {
3777 $pFather->load_stats_sending($socid, $filtrestatut, $forVirtualStock);
3779 $this->stats_expedition[
'customers'] += $pFather->stats_expedition[
'customers'];
3780 $this->stats_expedition[
'nb'] += $pFather->stats_expedition[
'nb'];
3781 $this->stats_expedition[
'rows'] += $pFather->stats_expedition[
'rows'];
3782 $this->stats_expedition[
'qty'] += $pFather->stats_expedition[
'qty'] * $qtyCoef;
3788 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock,
'filterShipmentStatus' => $filterShipmentStatus);
3789 $reshook = $hookmanager->executeHooks(
'loadStatsSending', $parameters, $this, $action);
3791 $this->stats_expedition = $hookmanager->resArray[
'stats_expedition'];
3796 $this->error = $this->db->error();
3811 public function load_stats_reception($socid = 0, $filtrestatut =
'', $forVirtualStock = 0, $dateofvirtualstock =
null)
3814 global $user, $hookmanager, $action;
3816 $sql =
"SELECT COUNT(DISTINCT cf.fk_soc) as nb_suppliers, COUNT(DISTINCT cf.rowid) as nb,";
3817 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(fd.qty) as qty";
3818 $sql .=
" FROM ".$this->db->prefix().
"receptiondet_batch as fd";
3819 $sql .=
", ".$this->db->prefix().
"commande_fournisseur as cf";
3820 $sql .=
", ".$this->db->prefix().
"societe as s";
3821 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3822 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3824 $sql .=
" WHERE cf.rowid = fd.fk_element";
3825 $sql .=
" AND cf.fk_soc = s.rowid";
3826 $sql .=
" AND cf.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'supplier_order').
")";
3827 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
3828 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3829 $sql .=
" AND cf.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3832 $sql .=
" AND cf.fk_soc = ".((int) $socid);
3834 if ($filtrestatut !=
'') {
3835 $sql .=
" AND cf.fk_statut IN (".$this->db->sanitize($filtrestatut).
")";
3837 if (!empty($dateofvirtualstock)) {
3838 $sql .=
" AND fd.datec <= '".$this->db->idate($dateofvirtualstock).
"'";
3841 $result = $this->db->query($sql);
3843 $obj = $this->db->fetch_object($result);
3844 $this->stats_reception[
'suppliers'] = $obj->nb_suppliers;
3845 $this->stats_reception[
'nb'] = $obj->nb;
3846 $this->stats_reception[
'rows'] = $obj->nb_rows;
3847 $this->stats_reception[
'qty'] = $obj->qty ? $obj->qty : 0;
3849 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3850 $reshook = $hookmanager->executeHooks(
'loadStatsReception', $parameters, $this, $action);
3852 $this->stats_reception = $hookmanager->resArray[
'stats_reception'];
3857 $this->error = $this->db->error();
3873 public function load_stats_inproduction($socid = 0, $filtrestatut =
'', $forVirtualStock = 0, $dateofvirtualstock =
null, $warehouseid = 0)
3876 global $user, $hookmanager, $action;
3878 $serviceStockIsEnabled = isModEnabled(
"service") &&
getDolGlobalString(
'STOCK_SUPPORTS_SERVICES');
3880 $sql =
"SELECT COUNT(DISTINCT m.fk_soc) as nb_customers, COUNT(DISTINCT m.rowid) as nb,";
3881 $sql .=
" COUNT(mp.rowid) as nb_rows, SUM(mp.qty) as qty, role";
3882 $sql .=
" FROM ".$this->db->prefix().
"mrp_production as mp";
3883 $sql .=
", ".$this->db->prefix().
"mrp_mo as m";
3884 $sql .=
" LEFT JOIN ".$this->db->prefix().
"societe as s ON s.rowid = m.fk_soc";
3885 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3886 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3888 $sql .=
" WHERE m.rowid = mp.fk_mo";
3889 $sql .=
" AND m.entity IN (".getEntity(($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE')) ?
'stock' :
'mrp').
")";
3890 $sql .=
" AND mp.fk_product = ".((int) $this->
id);
3891 $sql .=
" AND (mp.disable_stock_change IN (0) OR mp.disable_stock_change IS NULL)";
3892 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3893 $sql .=
" AND m.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3896 $sql .=
" AND m.fk_soc = ".((int) $socid);
3898 if ($filtrestatut !=
'') {
3899 $sql .=
" AND m.status IN (".$this->db->sanitize($filtrestatut).
")";
3901 if (!empty($dateofvirtualstock)) {
3902 $sql .=
" AND m.date_valid <= '".$this->db->idate($dateofvirtualstock).
"'";
3904 if (!$serviceStockIsEnabled) {
3905 $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))";
3907 if (!empty($warehouseid)) {
3908 $sql .=
" AND m.fk_warehouse = ".((int) $warehouseid);
3910 $sql .=
" GROUP BY role";
3913 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] = 0;
3915 $this->stats_mrptoconsume[
'customers'] = 0;
3916 $this->stats_mrptoconsume[
'nb'] = 0;
3917 $this->stats_mrptoconsume[
'rows'] = 0;
3918 $this->stats_mrptoconsume[
'qty'] = 0;
3919 $this->stats_mrptoproduce[
'customers'] = 0;
3920 $this->stats_mrptoproduce[
'nb'] = 0;
3921 $this->stats_mrptoproduce[
'rows'] = 0;
3922 $this->stats_mrptoproduce[
'qty'] = 0;
3925 $result = $this->db->query($sql);
3927 while ($obj = $this->db->fetch_object($result)) {
3928 if ($obj->role ==
'toconsume' && empty($warehouseid)) {
3929 $this->stats_mrptoconsume[
'customers'] += $obj->nb_customers;
3930 $this->stats_mrptoconsume[
'nb'] += $obj->nb;
3931 $this->stats_mrptoconsume[
'rows'] += $obj->nb_rows;
3932 $this->stats_mrptoconsume[
'qty'] += ($obj->qty ? $obj->qty : 0);
3934 if ($obj->role ==
'consumed' && empty($warehouseid)) {
3938 $this->stats_mrptoconsume[
'qty'] -= ($obj->qty ? $obj->qty : 0);
3940 if ($obj->role ==
'toproduce') {
3942 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] += ($obj->qty ? $obj->qty : 0);
3944 $this->stats_mrptoproduce[
'customers'] += $obj->nb_customers;
3945 $this->stats_mrptoproduce[
'nb'] += $obj->nb;
3946 $this->stats_mrptoproduce[
'rows'] += $obj->nb_rows;
3947 $this->stats_mrptoproduce[
'qty'] += ($obj->qty ? $obj->qty : 0);
3950 if ($obj->role ==
'produced') {
3955 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] -= ($obj->qty ? $obj->qty : 0);
3957 $this->stats_mrptoproduce[
'qty'] -= ($obj->qty ? $obj->qty : 0);
3964 if ($this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] < 0) {
3965 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] = 0;
3968 if ($this->stats_mrptoconsume[
'qty'] < 0) {
3969 $this->stats_mrptoconsume[
'qty'] = 0;
3971 if ($this->stats_mrptoproduce[
'qty'] < 0) {
3972 $this->stats_mrptoproduce[
'qty'] = 0;
3976 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3977 $reshook = $hookmanager->executeHooks(
'loadStatsInProduction', $parameters, $this, $action);
3979 $this->stats_mrptoproduce = $hookmanager->resArray[
'stats_mrptoproduce'];
3984 $this->error = $this->db->error();
3999 global $user, $hookmanager, $action;
4001 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,";
4002 $sql .=
" COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty";
4003 $sql .=
" FROM ".$this->db->prefix().
"contratdet as cd";
4004 $sql .=
", ".$this->db->prefix().
"contrat as c";
4005 $sql .=
", ".$this->db->prefix().
"societe as s";
4006 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4007 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4009 $sql .=
" WHERE c.rowid = cd.fk_contrat";
4010 $sql .=
" AND c.fk_soc = s.rowid";
4011 $sql .=
" AND c.entity IN (".getEntity(
'contract').
")";
4012 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
4013 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4014 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4018 $sql .=
" AND c.fk_soc = ".((int) $socid);
4021 $result = $this->db->query($sql);
4023 $obj = $this->db->fetch_object($result);
4024 $this->stats_contrat[
'customers'] = $obj->nb_customers;
4025 $this->stats_contrat[
'nb'] = $obj->nb;
4026 $this->stats_contrat[
'rows'] = $obj->nb_rows;
4027 $this->stats_contrat[
'qty'] = $obj->qty ? $obj->qty : 0;
4032 if (is_array($TFather) && !empty($TFather)) {
4033 foreach ($TFather as &$fatherData) {
4034 $pFather =
new Product($this->db);
4035 $pFather->id = $fatherData[
'id'];
4036 $qtyCoef = $fatherData[
'qty'];
4038 if ($fatherData[
'incdec']) {
4039 $pFather->load_stats_contrat($socid);
4041 $this->stats_contrat[
'customers'] += $pFather->stats_contrat[
'customers'];
4042 $this->stats_contrat[
'nb'] += $pFather->stats_contrat[
'nb'];
4043 $this->stats_contrat[
'rows'] += $pFather->stats_contrat[
'rows'];
4044 $this->stats_contrat[
'qty'] += $pFather->stats_contrat[
'qty'] * $qtyCoef;
4050 $parameters = array(
'socid' => $socid);
4051 $reshook = $hookmanager->executeHooks(
'loadStatsContract', $parameters, $this, $action);
4053 $this->stats_contrat = $hookmanager->resArray[
'stats_contrat'];
4058 $this->error = $this->db->error().
' sql='.$sql;
4073 global $user, $hookmanager, $action;
4075 $sql =
"SELECT COUNT(DISTINCT f.fk_soc) as nb_customers, COUNT(DISTINCT f.rowid) as nb,";
4076 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(".$this->db->ifsql(
'f.type != 2',
'fd.qty',
'fd.qty * -1').
") as qty";
4077 $sql .=
" FROM ".$this->db->prefix().
"facturedet as fd";
4078 $sql .=
", ".$this->db->prefix().
"facture as f";
4079 $sql .=
", ".$this->db->prefix().
"societe as s";
4080 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4081 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4083 $sql .=
" WHERE f.rowid = fd.fk_facture";
4084 $sql .=
" AND f.fk_soc = s.rowid";
4085 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4086 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
4087 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4088 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4092 $sql .=
" AND f.fk_soc = ".((int) $socid);
4095 $result = $this->db->query($sql);
4097 $obj = $this->db->fetch_object($result);
4098 $this->stats_facture[
'customers'] = $obj->nb_customers;
4099 $this->stats_facture[
'nb'] = $obj->nb;
4100 $this->stats_facture[
'rows'] = $obj->nb_rows;
4101 $this->stats_facture[
'qty'] = $obj->qty ? $obj->qty : 0;
4106 if (is_array($TFather) && !empty($TFather)) {
4107 foreach ($TFather as &$fatherData) {
4108 $pFather =
new Product($this->db);
4109 $pFather->id = $fatherData[
'id'];
4110 $qtyCoef = $fatherData[
'qty'];
4112 if ($fatherData[
'incdec']) {
4113 $pFather->load_stats_facture($socid);
4115 $this->stats_facture[
'customers'] += $pFather->stats_facture[
'customers'];
4116 $this->stats_facture[
'nb'] += $pFather->stats_facture[
'nb'];
4117 $this->stats_facture[
'rows'] += $pFather->stats_facture[
'rows'];
4118 $this->stats_facture[
'qty'] += $pFather->stats_facture[
'qty'] * $qtyCoef;
4124 $parameters = array(
'socid' => $socid);
4125 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerInvoice', $parameters, $this, $action);
4127 $this->stats_facture = $hookmanager->resArray[
'stats_facture'];
4132 $this->error = $this->db->error();
4148 global $user, $hookmanager, $action;
4150 $sql =
"SELECT COUNT(DISTINCT f.fk_soc) as nb_customers, COUNT(DISTINCT f.rowid) as nb,";
4151 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(fd.qty) as qty";
4152 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facturedet_rec as fd";
4153 $sql .=
", ".MAIN_DB_PREFIX.
"facture_rec as f";
4154 $sql .=
", ".MAIN_DB_PREFIX.
"societe as s";
4155 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4156 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
4158 $sql .=
" WHERE f.rowid = fd.fk_facture";
4159 $sql .=
" AND f.fk_soc = s.rowid";
4160 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4161 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
4162 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4163 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4167 $sql .=
" AND f.fk_soc = ".((int) $socid);
4170 $result = $this->db->query($sql);
4172 $obj = $this->db->fetch_object($result);
4173 $this->stats_facturerec[
'customers'] = $obj->nb_customers;
4174 $this->stats_facturerec[
'nb'] = $obj->nb;
4175 $this->stats_facturerec[
'rows'] = $obj->nb_rows;
4176 $this->stats_facturerec[
'qty'] = $obj->qty ? $obj->qty : 0;
4181 if (is_array($TFather) && !empty($TFather)) {
4182 foreach ($TFather as &$fatherData) {
4183 $pFather =
new Product($this->db);
4184 $pFather->id = $fatherData[
'id'];
4185 $qtyCoef = $fatherData[
'qty'];
4187 if ($fatherData[
'incdec']) {
4188 $pFather->load_stats_facture($socid);
4190 $this->stats_facturerec[
'customers'] += $pFather->stats_facturerec[
'customers'];
4191 $this->stats_facturerec[
'nb'] += $pFather->stats_facturerec[
'nb'];
4192 $this->stats_facturerec[
'rows'] += $pFather->stats_facturerec[
'rows'];
4193 $this->stats_facturerec[
'qty'] += $pFather->stats_facturerec[
'qty'] * $qtyCoef;
4199 $parameters = array(
'socid' => $socid);
4200 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerInvoiceRec', $parameters, $this, $action);
4202 $this->stats_facturerec = $hookmanager->resArray[
'stats_facturerec'];
4207 $this->error = $this->db->error();
4222 global $user, $hookmanager, $action;
4224 $sql =
"SELECT COUNT(DISTINCT f.fk_soc) as nb_suppliers, COUNT(DISTINCT f.rowid) as nb,";
4225 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(fd.qty) as qty";
4226 $sql .=
" FROM ".$this->db->prefix().
"facture_fourn_det as fd";
4227 $sql .=
", ".$this->db->prefix().
"facture_fourn as f";
4228 $sql .=
", ".$this->db->prefix().
"societe as s";
4229 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4230 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4232 $sql .=
" WHERE f.rowid = fd.fk_facture_fourn";
4233 $sql .=
" AND f.fk_soc = s.rowid";
4234 $sql .=
" AND f.entity IN (".getEntity(
'facture_fourn').
")";
4235 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
4236 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4237 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4241 $sql .=
" AND f.fk_soc = ".((int) $socid);
4244 $result = $this->db->query($sql);
4246 $obj = $this->db->fetch_object($result);
4247 $this->stats_facture_fournisseur[
'suppliers'] = $obj->nb_suppliers;
4248 $this->stats_facture_fournisseur[
'nb'] = $obj->nb;
4249 $this->stats_facture_fournisseur[
'rows'] = $obj->nb_rows;
4250 $this->stats_facture_fournisseur[
'qty'] = $obj->qty ? $obj->qty : 0;
4252 $parameters = array(
'socid' => $socid);
4253 $reshook = $hookmanager->executeHooks(
'loadStatsSupplierInvoice', $parameters, $this, $action);
4255 $this->stats_facture_fournisseur = $hookmanager->resArray[
'stats_facture_fournisseur'];
4260 $this->error = $this->db->error();
4279 $resql = $this->db->query($sql);
4281 $num = $this->db->num_rows($resql);
4284 $arr = $this->db->fetch_array($resql);
4285 if (is_array($arr)) {
4286 $keyfortab = (string) $arr[1];
4288 $keyfortab = substr($keyfortab, -2);
4291 if ($mode ==
'byunit') {
4292 $tab[$keyfortab] = (empty($tab[$keyfortab]) ? 0 : $tab[$keyfortab]) + $arr[0];
4293 } elseif ($mode ==
'bynumber') {
4294 $tab[$keyfortab] = (empty($tab[$keyfortab]) ? 0 : $tab[$keyfortab]) + $arr[2];
4295 } elseif ($mode ==
'byamount') {
4296 $tab[$keyfortab] = (empty($tab[$keyfortab]) ? 0 : $tab[$keyfortab]) + $arr[2];
4305 $this->error = $this->db->error().
' sql='.$sql;
4312 } elseif ($year == -1) {
4321 for ($j = 0; $j < 12; $j++) {
4323 $idx = ucfirst(
dol_trunc(
dol_print_date(
dol_mktime(12, 0, 0, $month, 1, 1970),
"%b"), 1,
'right',
'UTF-8', 1));
4326 $result[$j] = array($idx, isset($tab[$year.$month]) ? $tab[$year.$month] : 0);
4329 $month =
"0".($month - 1);
4331 $month = substr($month, 1);
4339 return array_reverse($result);
4354 public function get_nb_vente($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4359 $sql =
"SELECT sum(d.qty) as qty, date_format(f.datef, '%Y%m')";
4360 if ($mode ==
'bynumber') {
4361 $sql .=
", count(DISTINCT f.rowid)";
4363 $sql .=
", sum(d.total_ht) as total_ht";
4364 $sql .=
" FROM ".$this->db->prefix().
"facturedet as d, ".$this->db->prefix().
"facture as f, ".$this->db->prefix().
"societe as s";
4365 if ($filteronproducttype >= 0) {
4366 $sql .=
", ".$this->db->prefix().
"product as p";
4368 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4369 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4371 $sql .=
" WHERE f.rowid = d.fk_facture";
4372 if ($this->
id > 0) {
4373 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4375 $sql .=
" AND d.fk_product > 0";
4377 if ($filteronproducttype >= 0) {
4378 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4380 $sql .=
" AND f.fk_soc = s.rowid";
4381 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4382 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4383 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4386 $sql .=
" AND f.fk_soc = $socid";
4388 $sql .= $morefilter;
4389 $sql .=
" GROUP BY date_format(f.datef,'%Y%m')";
4390 $sql .=
" ORDER BY date_format(f.datef,'%Y%m') DESC";
4392 return $this->
_get_stats($sql, $mode, $year);
4407 public function get_nb_achat($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4412 $sql =
"SELECT sum(d.qty) as qty, date_format(f.datef, '%Y%m')";
4413 if ($mode ==
'bynumber') {
4414 $sql .=
", count(DISTINCT f.rowid)";
4416 $sql .=
", sum(d.total_ht) as total_ht";
4417 $sql .=
" FROM ".$this->db->prefix().
"facture_fourn_det as d, ".$this->db->prefix().
"facture_fourn as f, ".$this->db->prefix().
"societe as s";
4418 if ($filteronproducttype >= 0) {
4419 $sql .=
", ".$this->db->prefix().
"product as p";
4421 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4422 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4424 $sql .=
" WHERE f.rowid = d.fk_facture_fourn";
4425 if ($this->
id > 0) {
4426 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4428 $sql .=
" AND d.fk_product > 0";
4430 if ($filteronproducttype >= 0) {
4431 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4433 $sql .=
" AND f.fk_soc = s.rowid";
4434 $sql .=
" AND f.entity IN (".getEntity(
'facture_fourn').
")";
4435 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4436 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4439 $sql .=
" AND f.fk_soc = $socid";
4441 $sql .= $morefilter;
4442 $sql .=
" GROUP BY date_format(f.datef,'%Y%m')";
4443 $sql .=
" ORDER BY date_format(f.datef,'%Y%m') DESC";
4445 return $this->
_get_stats($sql, $mode, $year);
4459 public function get_nb_propal($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4464 $sql =
"SELECT sum(d.qty) as qty, date_format(p.datep, '%Y%m')";
4465 if ($mode ==
'bynumber') {
4466 $sql .=
", count(DISTINCT p.rowid)";
4468 $sql .=
", sum(d.total_ht) as total_ht";
4469 $sql .=
" FROM ".$this->db->prefix().
"propaldet as d, ".$this->db->prefix().
"propal as p, ".$this->db->prefix().
"societe as s";
4470 if ($filteronproducttype >= 0) {
4471 $sql .=
", ".$this->db->prefix().
"product as prod";
4473 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4474 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4476 $sql .=
" WHERE p.rowid = d.fk_propal";
4477 if ($this->
id > 0) {
4478 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4480 $sql .=
" AND d.fk_product > 0";
4482 if ($filteronproducttype >= 0) {
4483 $sql .=
" AND prod.rowid = d.fk_product AND prod.fk_product_type = ".((int) $filteronproducttype);
4485 $sql .=
" AND p.fk_soc = s.rowid";
4486 $sql .=
" AND p.entity IN (".getEntity(
'propal').
")";
4487 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4488 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4491 $sql .=
" AND p.fk_soc = ".((int) $socid);
4493 $sql .= $morefilter;
4494 $sql .=
" GROUP BY date_format(p.datep,'%Y%m')";
4495 $sql .=
" ORDER BY date_format(p.datep,'%Y%m') DESC";
4497 return $this->
_get_stats($sql, $mode, $year);
4516 $sql =
"SELECT sum(d.qty) as qty, date_format(p.date_valid, '%Y%m')";
4517 if ($mode ==
'bynumber') {
4518 $sql .=
", count(DISTINCT p.rowid)";
4520 $sql .=
", sum(d.total_ht) as total_ht";
4521 $sql .=
" FROM ".$this->db->prefix().
"supplier_proposaldet as d, ".$this->db->prefix().
"supplier_proposal as p, ".$this->db->prefix().
"societe as s";
4522 if ($filteronproducttype >= 0) {
4523 $sql .=
", ".$this->db->prefix().
"product as prod";
4525 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4526 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4528 $sql .=
" WHERE p.rowid = d.fk_supplier_proposal";
4529 if ($this->
id > 0) {
4530 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4532 $sql .=
" AND d.fk_product > 0";
4534 if ($filteronproducttype >= 0) {
4535 $sql .=
" AND prod.rowid = d.fk_product AND prod.fk_product_type = ".((int) $filteronproducttype);
4537 $sql .=
" AND p.fk_soc = s.rowid";
4538 $sql .=
" AND p.entity IN (".getEntity(
'supplier_proposal').
")";
4539 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4540 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4543 $sql .=
" AND p.fk_soc = ".((int) $socid);
4545 $sql .= $morefilter;
4546 $sql .=
" GROUP BY date_format(p.date_valid,'%Y%m')";
4547 $sql .=
" ORDER BY date_format(p.date_valid,'%Y%m') DESC";
4549 return $this->
_get_stats($sql, $mode, $year);
4563 public function get_nb_order($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4568 $sql =
"SELECT sum(d.qty) as qty, date_format(c.date_commande, '%Y%m')";
4569 if ($mode ==
'bynumber') {
4570 $sql .=
", count(DISTINCT c.rowid)";
4572 $sql .=
", sum(d.total_ht) as total_ht";
4573 $sql .=
" FROM ".$this->db->prefix().
"commandedet as d, ".$this->db->prefix().
"commande as c, ".$this->db->prefix().
"societe as s";
4574 if ($filteronproducttype >= 0) {
4575 $sql .=
", ".$this->db->prefix().
"product as p";
4577 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4578 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4580 $sql .=
" WHERE c.rowid = d.fk_commande";
4581 if ($this->
id > 0) {
4582 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4584 $sql .=
" AND d.fk_product > 0";
4586 if ($filteronproducttype >= 0) {
4587 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4589 $sql .=
" AND c.fk_soc = s.rowid";
4590 $sql .=
" AND c.entity IN (".getEntity(
'commande').
")";
4591 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4592 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4595 $sql .=
" AND c.fk_soc = ".((int) $socid);
4597 $sql .= $morefilter;
4598 $sql .=
" GROUP BY date_format(c.date_commande,'%Y%m')";
4599 $sql .=
" ORDER BY date_format(c.date_commande,'%Y%m') DESC";
4601 return $this->
_get_stats($sql, $mode, $year);
4620 $sql =
"SELECT sum(d.qty) as qty, date_format(c.date_commande, '%Y%m')";
4621 if ($mode ==
'bynumber') {
4622 $sql .=
", count(DISTINCT c.rowid)";
4624 $sql .=
", sum(d.total_ht) as total_ht";
4625 $sql .=
" FROM ".$this->db->prefix().
"commande_fournisseurdet as d, ".$this->db->prefix().
"commande_fournisseur as c, ".$this->db->prefix().
"societe as s";
4626 if ($filteronproducttype >= 0) {
4627 $sql .=
", ".$this->db->prefix().
"product as p";
4629 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4630 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4632 $sql .=
" WHERE c.rowid = d.fk_commande";
4633 if ($this->
id > 0) {
4634 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4636 $sql .=
" AND d.fk_product > 0";
4638 if ($filteronproducttype >= 0) {
4639 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4641 $sql .=
" AND c.fk_soc = s.rowid";
4642 $sql .=
" AND c.entity IN (".getEntity(
'supplier_order').
")";
4643 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4644 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4647 $sql .=
" AND c.fk_soc = ".((int) $socid);
4649 $sql .= $morefilter;
4650 $sql .=
" GROUP BY date_format(c.date_commande,'%Y%m')";
4651 $sql .=
" ORDER BY date_format(c.date_commande,'%Y%m') DESC";
4653 return $this->
_get_stats($sql, $mode, $year);
4667 public function get_nb_contract($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4672 $sql =
"SELECT sum(d.qty) as qty, date_format(c.date_contrat, '%Y%m')";
4673 if ($mode ==
'bynumber') {
4674 $sql .=
", count(DISTINCT c.rowid)";
4676 $sql .=
", sum(d.total_ht) as total_ht";
4677 $sql .=
" FROM ".$this->db->prefix().
"contratdet as d, ".$this->db->prefix().
"contrat as c, ".$this->db->prefix().
"societe as s";
4678 if ($filteronproducttype >= 0) {
4679 $sql .=
", ".$this->db->prefix().
"product as p";
4681 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4682 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4684 $sql .=
" WHERE c.entity IN (".getEntity(
'contract').
")";
4685 $sql .=
" AND c.rowid = d.fk_contrat";
4687 if ($this->
id > 0) {
4688 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4690 $sql .=
" AND d.fk_product > 0";
4692 if ($filteronproducttype >= 0) {
4693 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4695 $sql .=
" AND c.fk_soc = s.rowid";
4697 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4698 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4701 $sql .=
" AND c.fk_soc = ".((int) $socid);
4703 $sql .= $morefilter;
4704 $sql .=
" GROUP BY date_format(c.date_contrat,'%Y%m')";
4705 $sql .=
" ORDER BY date_format(c.date_contrat,'%Y%m') DESC";
4707 return $this->
_get_stats($sql, $mode, $year);
4721 public function get_nb_mos($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4726 $sql =
"SELECT sum(d.qty), date_format(d.date_valid, '%Y%m')";
4727 if ($mode ==
'bynumber') {
4728 $sql .=
", count(DISTINCT d.rowid)";
4730 $sql .=
" FROM ".$this->db->prefix().
"mrp_mo as d LEFT JOIN ".$this->db->prefix().
"societe as s ON d.fk_soc = s.rowid";
4731 if ($filteronproducttype >= 0) {
4732 $sql .=
", ".$this->db->prefix().
"product as p";
4734 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4735 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4738 $sql .=
" WHERE d.entity IN (".getEntity(
'mo').
")";
4739 $sql .=
" AND d.status > 0";
4741 if ($this->
id > 0) {
4742 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4744 $sql .=
" AND d.fk_product > 0";
4746 if ($filteronproducttype >= 0) {
4747 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4750 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4751 $sql .=
" AND d.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4754 $sql .=
" AND d.fk_soc = ".((int) $socid);
4756 $sql .= $morefilter;
4757 $sql .=
" GROUP BY date_format(d.date_valid,'%Y%m')";
4758 $sql .=
" ORDER BY date_format(d.date_valid,'%Y%m') DESC";
4760 return $this->
_get_stats($sql, $mode, $year);
4780 if (!is_numeric($id_pere)) {
4783 if (!is_numeric($id_fils)) {
4786 if (!is_numeric($incdec)) {
4796 $sql =
"SELECT fk_product_pere from ".$this->db->prefix().
"product_association";
4797 $sql .=
" WHERE fk_product_pere = ".((int) $id_fils).
" AND fk_product_fils = ".((int) $id_pere);
4798 if (!$this->db->query($sql)) {
4803 $sql =
"SELECT MAX(rang) as max_rank FROM ".$this->db->prefix().
"product_association";
4804 $sql .=
" WHERE fk_product_pere = ".((int) $id_pere);
4805 $resql = $this->db->query($sql);
4807 $obj = $this->db->fetch_object($resql);
4808 $rank = $obj->max_rank + 1;
4810 $sql =
"INSERT INTO ".$this->db->prefix().
"product_association(fk_product_pere,fk_product_fils,qty,incdec,rang)";
4811 $sql .=
" VALUES (".((int) $id_pere).
", ".((int) $id_fils).
", ".
price2num($qty,
'MS').
", ".((int) $incdec).
", ".((int) $rank).
")";
4812 if (! $this->db->query($sql)) {
4818 $result = $this->
call_trigger(
'PRODUCT_SUBPRODUCT_ADD', $user);
4820 $this->error = $this->db->lasterror();
4821 dol_syslog(get_class($this).
'::addSubproduct error='.$this->error, LOG_ERR);
4853 if (!is_numeric($id_pere)) {
4856 if (!is_numeric($id_fils)) {
4859 if (!is_numeric($incdec)) {
4862 if (!is_numeric($qty)) {
4866 $sql =
'UPDATE '.$this->db->prefix().
'product_association SET ';
4867 $sql .=
'qty = '.price2num($qty,
'MS');
4868 $sql .=
',incdec = '.((int) $incdec);
4869 $sql .=
' WHERE fk_product_pere = '.((int) $id_pere).
' AND fk_product_fils = '.((int) $id_fils);
4871 if (!$this->db->query($sql)) {
4877 $result = $this->
call_trigger(
'PRODUCT_SUBPRODUCT_UPDATE', $user);
4879 $this->error = $this->db->lasterror();
4880 dol_syslog(get_class($this).
'::updateSubproduct error='.$this->error, LOG_ERR);
4904 if (!is_numeric($fk_parent)) {
4907 if (!is_numeric($fk_child)) {
4911 $sql =
"DELETE FROM ".$this->db->prefix().
"product_association";
4912 $sql .=
" WHERE fk_product_pere = ".((int) $fk_parent);
4913 $sql .=
" AND fk_product_fils = ".((int) $fk_child);
4915 dol_syslog(get_class($this).
'::del_sousproduit', LOG_DEBUG);
4916 if (!$this->db->query($sql)) {
4922 $sqlrank =
"SELECT rowid, rang FROM ".$this->db->prefix().
"product_association";
4923 $sqlrank .=
" WHERE fk_product_pere = ".((int) $fk_parent);
4924 $sqlrank .=
" ORDER BY rang";
4925 $resqlrank = $this->db->query($sqlrank);
4928 while ($objrank = $this->db->fetch_object($resqlrank)) {
4930 $sql =
"UPDATE ".$this->db->prefix().
"product_association";
4931 $sql .=
" SET rang = ".((int) $cpt);
4932 $sql .=
" WHERE rowid = ".((int) $objrank->rowid);
4933 if (! $this->db->query($sql)) {
4942 $result = $this->
call_trigger(
'PRODUCT_SUBPRODUCT_DELETE', $user);
4944 $this->error = $this->db->lasterror();
4945 dol_syslog(get_class($this).
'::delSubproduct error='.$this->error, LOG_ERR);
4965 $sql =
"SELECT fk_product_pere, qty, incdec";
4966 $sql .=
" FROM ".$this->db->prefix().
"product_association";
4967 $sql .=
" WHERE fk_product_pere = ".((int) $fk_parent);
4968 $sql .=
" AND fk_product_fils = ".((int) $fk_child);
4970 $result = $this->db->query($sql);
4972 $num = $this->db->num_rows($result);
4975 $obj = $this->db->fetch_object($result);
4977 $this->is_sousproduit_qty = $obj->qty;
4978 $this->is_sousproduit_incdec = $obj->incdec;
5009 dol_syslog(get_class($this).
"::add_fournisseur id_fourn = ".$id_fourn.
" ref_fourn=".$ref_fourn.
" quantity=".$quantity, LOG_DEBUG);
5016 $sql =
"SELECT rowid, fk_product";
5017 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price";
5018 $sql .=
" WHERE fk_soc = ".((int) $id_fourn);
5019 $sql .=
" AND ref_fourn = '".$this->db->escape($ref_fourn).
"'";
5020 $sql .=
" AND fk_product <> ".((int) $this->
id);
5021 $sql .=
" AND entity IN (".getEntity(
'productsupplierprice').
")";
5023 $resql = $this->db->query($sql);
5025 $obj = $this->db->fetch_object($resql);
5028 $this->product_id_already_linked = $obj->fk_product;
5031 $this->db->free($resql);
5035 $sql =
"SELECT rowid";
5036 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price";
5037 $sql .=
" WHERE fk_soc = ".((int) $id_fourn);
5039 $sql .=
" AND ref_fourn = '".$this->db->escape($ref_fourn).
"'";
5041 $sql .=
" AND (ref_fourn = '' OR ref_fourn IS NULL)";
5043 $sql .=
" AND quantity = ".((float) $quantity);
5044 $sql .=
" AND fk_product = ".((int) $this->
id);
5045 $sql .=
" AND entity IN (".getEntity(
'productsupplierprice').
")";
5047 $resql = $this->db->query($sql);
5049 $obj = $this->db->fetch_object($resql);
5053 $sql =
"INSERT INTO ".$this->db->prefix().
"product_fournisseur_price(";
5056 $sql .=
", fk_product";
5058 $sql .=
", ref_fourn";
5059 $sql .=
", quantity";
5060 $sql .=
", fk_user";
5062 $sql .=
") VALUES (";
5063 $sql .=
"'".$this->db->idate($now).
"'";
5064 $sql .=
", ".((int) $conf->entity);
5065 $sql .=
", ".((int) $this->
id);
5066 $sql .=
", ".((int) $id_fourn);
5067 $sql .=
", '".$this->db->escape($ref_fourn).
"'";
5068 $sql .=
", ".((float) $quantity);
5069 $sql .=
", ".((int) $user->id);
5073 if ($this->db->query($sql)) {
5074 $this->product_fourn_price_id = $this->db->last_insert_id($this->db->prefix().
"product_fournisseur_price");
5077 $this->error = $this->db->lasterror();
5082 $this->product_fourn_price_id = $obj->rowid;
5086 $this->error = $this->db->lasterror();
5105 $sql =
"SELECT DISTINCT p.fk_soc";
5106 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price as p";
5107 $sql .=
" WHERE p.fk_product = ".((int) $this->
id);
5108 $sql .=
" AND p.entity = ".((int) $conf->entity);
5110 $result = $this->db->query($sql);
5112 $num = $this->db->num_rows($result);
5115 $obj = $this->db->fetch_object($result);
5116 $list[$i] = $obj->fk_soc;
5141 $sql =
"INSERT INTO ".$this->db->prefix().
"product_price (";
5143 $sql .=
", fk_product";
5144 $sql .=
", date_price";
5145 $sql .=
", price_level";
5147 $sql .=
", price_ttc";
5148 $sql .=
", price_min";
5149 $sql .=
", price_min_ttc";
5150 $sql .=
", price_base_type";
5151 $sql .=
", price_label";
5152 $sql .=
", default_vat_code";
5154 $sql .=
", recuperableonly";
5155 $sql .=
", localtax1_tx";
5156 $sql .=
", localtax1_type";
5157 $sql .=
", localtax2_tx";
5158 $sql .=
", localtax2_type";
5159 $sql .=
", fk_user_author";
5161 $sql .=
", price_by_qty";
5162 $sql .=
", fk_price_expression";
5163 $sql .=
", fk_multicurrency";
5164 $sql .=
", multicurrency_code";
5165 $sql .=
", multicurrency_tx";
5166 $sql .=
", multicurrency_price";
5167 $sql .=
", multicurrency_price_ttc";
5172 $sql .=
", '".$this->db->idate($now).
"'";
5173 $sql .=
", price_level";
5175 $sql .=
", price_ttc";
5176 $sql .=
", price_min";
5177 $sql .=
", price_min_ttc";
5178 $sql .=
", price_base_type";
5179 $sql .=
", price_label";
5180 $sql .=
", default_vat_code";
5182 $sql .=
", recuperableonly";
5183 $sql .=
", localtax1_tx";
5184 $sql .=
", localtax1_type";
5185 $sql .=
", localtax2_tx";
5186 $sql .=
", localtax2_type";
5187 $sql .=
", ".$user->id;
5189 $sql .=
", price_by_qty";
5190 $sql .=
", fk_price_expression";
5191 $sql .=
", fk_multicurrency";
5192 $sql .=
", multicurrency_code";
5193 $sql .=
", multicurrency_tx";
5194 $sql .=
", multicurrency_price";
5195 $sql .=
", multicurrency_price_ttc";
5196 $sql .=
" FROM ".$this->db->prefix().
"product_price ps";
5197 $sql .=
" WHERE fk_product = ".((int) $fromId);
5198 $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)";
5199 $sql .=
" ORDER BY date_price DESC";
5202 $resql = $this->db->query($sql);
5204 $this->db->rollback();
5208 $this->db->commit();
5225 $sql =
'INSERT INTO '.$this->db->prefix().
'product_association (fk_product_pere, fk_product_fils, qty, incdec)';
5226 $sql .=
" SELECT ".$toId.
", fk_product_fils, qty, incdec FROM ".$this->db->prefix().
"product_association";
5227 $sql .=
" WHERE fk_product_pere = ".((int) $fromId);
5229 dol_syslog(get_class($this).
'::clone_association', LOG_DEBUG);
5230 if (!$this->db->query($sql)) {
5231 $this->db->rollback();
5235 $this->db->commit();
5268 $sql =
"INSERT ".$this->db->prefix().
"product_fournisseur_price (";
5269 $sql .=
" datec, fk_product, fk_soc, price, quantity, fk_user, tva_tx)";
5270 $sql .=
" SELECT '".$this->db->idate($now).
"', ".((int) $toId).
", fk_soc, price, quantity, fk_user, tva_tx";
5271 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price";
5272 $sql .=
" WHERE fk_product = ".((int) $fromId);
5274 dol_syslog(get_class($this).
'::clone_fournisseurs', LOG_DEBUG);
5275 $resql = $this->db->query($sql);
5277 $this->db->rollback();
5280 $this->db->commit();
5298 public function fetch_prod_arbo($prod, $compl_path =
'', $multiply = 1, $level = 1, $id_parent = 0, $ignore_stock_load = 0)
5304 foreach ($prod as $id_product => $desc_pere) {
5305 if (is_array($desc_pere)) {
5306 $id = (!empty($desc_pere[0]) ? $desc_pere[0] :
'');
5307 $nb = (!empty($desc_pere[1]) ? $desc_pere[1] :
'');
5308 $type = (!empty($desc_pere[2]) ? $desc_pere[2] :
'');
5309 $label = (!empty($desc_pere[3]) ? $desc_pere[3] :
'');
5310 $incdec = (!empty($desc_pere[4]) ? $desc_pere[4] : 0);
5312 if ($multiply < 1) {
5317 if (is_null($tmpproduct)) {
5318 $tmpproduct =
new Product($this->db);
5320 $tmpproduct->fetch($id);
5322 if (empty($ignore_stock_load) && ($tmpproduct->isProduct() ||
getDolGlobalString(
'STOCK_SUPPORTS_SERVICES'))) {
5323 $tmpproduct->load_stock(
'nobatch,novirtual');
5326 $this->res[] = array(
5328 'id_parent' => $id_parent,
5329 'ref' => $tmpproduct->ref,
5331 'nb_total' => $nb * $multiply,
5332 'stock' => $tmpproduct->stock_reel,
5333 'stock_alert' => $tmpproduct->seuil_stock_alerte,
5335 'fullpath' => $compl_path.$label,
5337 'desiredstock' => $tmpproduct->desiredstock,
5339 'incdec' => $incdec,
5340 'entity' => $tmpproduct->entity
5344 if (isset($desc_pere[
'childs']) && is_array($desc_pere[
'childs'])) {
5346 $this->
fetch_prod_arbo($desc_pere[
'childs'], $compl_path.$desc_pere[3].
" -> ", $desc_pere[1] * $multiply, $level + 1, $id, $ignore_stock_load);
5364 $this->res = array();
5365 if (isset($this->sousprods) && is_array($this->sousprods)) {
5366 foreach ($this->sousprods as $prod_name => $desc_product) {
5367 if (is_array($desc_product)) {
5368 $this->
fetch_prod_arbo($desc_product,
"", $multiply, 1, $this->
id, $ignore_stock_load);
5387 $sql =
"SELECT COUNT(pa.rowid) as nb";
5388 $sql .=
" FROM ".$this->db->prefix().
"product_association as pa";
5390 $sql .=
" WHERE pa.fk_product_fils = ".((int) $this->
id).
" OR pa.fk_product_pere = ".((int) $this->
id);
5391 } elseif ($mode == -1) {
5392 $sql .=
" WHERE pa.fk_product_fils = ".((int) $this->
id);
5393 } elseif ($mode == 1) {
5394 $sql .=
" WHERE pa.fk_product_pere = ".((int) $this->
id);
5397 $resql = $this->db->query($sql);
5399 $obj = $this->db->fetch_object($resql);
5418 $sql =
"SELECT count(rowid) as nb FROM ".$this->db->prefix().
"product_attribute_combination WHERE fk_product_parent = ".((int) $this->
id);
5419 $sql .=
" AND entity IN (".getEntity(
'product').
")";
5421 $resql = $this->db->query($sql);
5423 $obj = $this->db->fetch_object($resql);
5440 if (isModEnabled(
'variants')) {
5441 $sql =
"SELECT rowid FROM ".$this->db->prefix().
"product_attribute_combination WHERE fk_product_child = ".((int) $this->
id).
" AND entity IN (".
getEntity(
'product').
")";
5443 $query = $this->db->query($sql);
5446 if (!$this->db->num_rows($query)) {
5467 $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";
5468 $sql .=
", p.tosell as status, p.tobuy as status_buy";
5469 $sql .=
" FROM ".$this->db->prefix().
"product_association as pa,";
5470 $sql .=
" ".$this->db->prefix().
"product as p";
5471 $sql .=
" WHERE p.rowid = pa.fk_product_pere";
5472 $sql .=
" AND pa.fk_product_fils = ".((int) $this->
id);
5474 $res = $this->db->query($sql);
5477 while ($record = $this->db->fetch_array($res)) {
5479 $prods[$record[
'id']][
'id'] = $record[
'rowid'];
5480 $prods[$record[
'id']][
'ref'] = $record[
'ref'];
5481 $prods[$record[
'id']][
'label'] = $record[
'label'];
5482 $prods[$record[
'id']][
'qty'] = $record[
'qty'];
5483 $prods[$record[
'id']][
'incdec'] = $record[
'incdec'];
5484 $prods[$record[
'id']][
'fk_product_type'] = $record[
'fk_product_type'];
5485 $prods[$record[
'id']][
'entity'] = $record[
'entity'];
5486 $prods[$record[
'id']][
'status'] = $record[
'status'];
5487 $prods[$record[
'id']][
'status_buy'] = $record[
'status_buy'];
5506 public function getChildsArbo($id, $firstlevelonly = 0, $level = 1, $parents = array())
5508 global $alreadyfound;
5514 $sql =
"SELECT p.rowid, p.ref, p.label as label, p.fk_product_type,";
5515 $sql .=
" pa.qty as qty, pa.fk_product_fils as id, pa.incdec,";
5516 $sql .=
" pa.rowid as fk_association, pa.rang";
5517 $sql .=
" FROM ".$this->db->prefix().
"product as p,";
5518 $sql .=
" ".$this->db->prefix().
"product_association as pa";
5519 $sql .=
" WHERE p.rowid = pa.fk_product_fils";
5520 $sql .=
" AND pa.fk_product_pere = ".((int) $id);
5521 $sql .=
" AND pa.fk_product_fils <> ".((int) $id);
5522 $sql .=
" ORDER BY pa.rang";
5524 dol_syslog(get_class($this).
'::getChildsArbo id='.$id.
' level='.$level.
' parents='.(is_array($parents) ? implode(
',', $parents) : $parents), LOG_DEBUG);
5527 $alreadyfound = array($id => 1);
5534 $res = $this->db->query($sql);
5537 while ($rec = $this->db->fetch_array($res)) {
5538 if (!empty($alreadyfound[$rec[
'rowid']])) {
5539 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);
5540 if (in_array($rec[
'id'], $parents)) {
5544 $alreadyfound[$rec[
'rowid']] = 1;
5545 $prods[$rec[
'rowid']] = array(
5548 2 => $rec[
'fk_product_type'],
5549 3 => $this->db->escape($rec[
'label']),
5550 4 => $rec[
'incdec'],
5552 6 => $rec[
'fk_association'],
5557 if (empty($firstlevelonly)) {
5558 $parents[] = $rec[
'rowid'];
5559 $listofchilds = $this->
getChildsArbo($rec[
'rowid'], 0, $level + 1, $parents);
5560 foreach ($listofchilds as $keyChild => $valueChild) {
5561 $prods[$rec[
'rowid']][
'childs'][$keyChild] = $valueChild;
5585 foreach ($this->
getChildsArbo($this->
id) as $keyChild => $valueChild) {
5586 $parent[$this->label][$keyChild] = $valueChild;
5588 foreach ($parent as $key => $value) {
5589 $this->sousprods[$key] = $value;
5602 global $conf, $langs, $user;
5604 $langs->loadLangs(array(
'products',
'other'));
5607 $nofetch = !empty($params[
'nofetch']);
5610 return [
'optimize' => $langs->trans(
"ShowProduct")];
5614 $permissiontoreadproduct = 0;
5615 if ($this->
type == self::TYPE_PRODUCT && $user->hasRight(
'product',
'read')) {
5616 $permissiontoreadproduct = 1;
5618 if ($this->
type == self::TYPE_SERVICE && $user->hasRight(
'service',
'read')) {
5619 $permissiontoreadproduct = 1;
5622 if (!empty($this->entity) && $permissiontoreadproduct) {
5623 $tmpphoto = $this->
show_photos(
'product', $conf->product->multidir_output[$this->entity], 1, 1, 0, 0, 0, 80, 0, 0, 0, 0,
'1');
5624 if ($this->nbphoto > 0) {
5625 $datas[
'photo'] =
'<div class="photointooltip floatright">'.
"\n" . $tmpphoto .
'</div>';
5630 $datas[
'picto'] =
img_picto(
'',
'product').
' <u class="paddingrightonly">'.$langs->trans(
"Product").
'</u>';
5632 $datas[
'picto'] =
img_picto(
'',
'service').
' <u class="paddingrightonly">'.$langs->trans(
"Service").
'</u>';
5634 if (isset($this->
status) && isset($this->status_buy)) {
5635 $datas[
'status'] =
' '.$this->getLibStatut(5, 0) .
' '.$this->getLibStatut(5, 1);
5638 if (!empty($this->
ref)) {
5639 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'ProductRef').
':</b> '.$this->ref;
5641 if (!empty($this->label)) {
5642 $datas[
'label'] =
'<br><b>'.$langs->trans(
'ProductLabel').
':</b> '.$this->label;
5645 if ($permissiontoreadproduct) {
5650 if (isModEnabled(
'productbatch')) {
5651 $langs->load(
"productbatch");
5652 $datas[
'batchstatus'] =
"<br><b>".$langs->trans(
"ManageLotSerial").
'</b>: '.$this->
getLibStatut(0, 2);
5655 if (isModEnabled(
'barcode')) {
5656 $datas[
'barcode'] =
'<br><b>'.$langs->trans(
'BarCode').
':</b> '.$this->barcode;
5660 if ($this->weight) {
5661 $datas[
'weight'] =
"<br><b>".$langs->trans(
"Weight").
'</b>: '.$this->weight.
' '.
measuringUnitString(0,
"weight", $this->weight_units);
5664 if ($this->length) {
5665 $labelsize .= ($labelsize ?
" - " :
"").
"<b>".$langs->trans(
"Length").
'</b>: '.$this->length.
' '.
measuringUnitString(0,
'size', $this->length_units);
5668 $labelsize .= ($labelsize ?
" - " :
"").
"<b>".$langs->trans(
"Width").
'</b>: '.$this->width.
' '.
measuringUnitString(0,
'size', $this->width_units);
5670 if ($this->height) {
5671 $labelsize .= ($labelsize ?
" - " :
"").
"<b>".$langs->trans(
"Height").
'</b>: '.$this->height.
' '.
measuringUnitString(0,
'size', $this->height_units);
5674 $datas[
'size'] =
"<br>".$labelsize;
5677 $labelsurfacevolume =
"";
5678 if ($this->surface) {
5679 $labelsurfacevolume .= ($labelsurfacevolume ?
" - " :
"").
"<b>".$langs->trans(
"Surface").
'</b>: '.$this->surface.
' '.
measuringUnitString(0,
'surface', $this->surface_units);
5681 if ($this->volume) {
5682 $labelsurfacevolume .= ($labelsurfacevolume ?
" - " :
"").
"<b>".$langs->trans(
"Volume").
'</b>: '.$this->volume.
' '.
measuringUnitString(0,
'volume', $this->volume_units);
5684 if ($labelsurfacevolume) {
5685 $datas[
'surface'] =
"<br>" . $labelsurfacevolume;
5688 if ($this->
isService() && !empty($this->duration_value)) {
5690 $datas[
'duration'] =
'<br><b>'.$langs->trans(
"Duration").
':</b> '.$this->duration_value;
5691 if ($this->duration_value > 1) {
5692 $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"));
5693 } elseif ($this->duration_value > 0) {
5694 $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"));
5696 $datas[
'duration'] .= (!empty($this->duration_unit) && isset($dur[$this->duration_unit]) ?
" ".$langs->trans($dur[$this->duration_unit]) :
'');
5698 if (empty($user->socid)) {
5699 if (!empty($this->pmp) && $this->pmp) {
5700 $datas[
'pmp'] =
"<br><b>".$langs->trans(
"PMPValue").
'</b>: '.
price($this->pmp, 0,
'', 1, -1, -1, $conf->currency);
5703 if (isModEnabled(
'accounting')) {
5704 if ($this->
status && isset($this->accountancy_code_sell)) {
5705 include_once DOL_DOCUMENT_ROOT.
'/core/lib/accounting.lib.php';
5706 $selllabel =
'<br>';
5707 $selllabel .=
'<br><b>'.$langs->trans(
'ProductAccountancySellCode').
':</b> '.
length_accountg($this->accountancy_code_sell);
5708 $selllabel .=
'<br><b>'.$langs->trans(
'ProductAccountancySellIntraCode').
':</b> '.
length_accountg($this->accountancy_code_sell_intra);
5709 $selllabel .=
'<br><b>'.$langs->trans(
'ProductAccountancySellExportCode').
':</b> '.
length_accountg($this->accountancy_code_sell_export);
5710 $datas[
'accountancysell'] = $selllabel;
5712 if ($this->status_buy && isset($this->accountancy_code_buy)) {
5713 include_once DOL_DOCUMENT_ROOT.
'/core/lib/accounting.lib.php';
5715 if (empty($this->
status)) {
5716 $buylabel .=
'<br>';
5718 $buylabel .=
'<br><b>'.$langs->trans(
'ProductAccountancyBuyCode').
':</b> '.
length_accountg($this->accountancy_code_buy);
5719 $buylabel .=
'<br><b>'.$langs->trans(
'ProductAccountancyBuyIntraCode').
':</b> '.
length_accountg($this->accountancy_code_buy_intra);
5720 $buylabel .=
'<br><b>'.$langs->trans(
'ProductAccountancyBuyExportCode').
':</b> '.
length_accountg($this->accountancy_code_buy_export);
5721 $datas[
'accountancybuy'] = $buylabel;
5726 if (isModEnabled(
'category') && !$nofetch) {
5727 require_once DOL_DOCUMENT_ROOT .
'/categories/class/categorie.class.php';
5728 $form =
new Form($this->db);
5729 $datas[
'categories'] =
'<br>' . $form->showCategories($this->
id, Categorie::TYPE_PRODUCT, 1);
5749 public function getNomUrl($withpicto = 0, $option =
'', $maxlength = 0, $save_lastsearch_value = -1, $notooltip = 0, $morecss =
'', $add_label = 0, $sep =
' - ')
5751 global $langs, $hookmanager;
5753 include_once DOL_DOCUMENT_ROOT.
'/core/lib/product.lib.php';
5757 $newref = $this->ref;
5759 $newref =
dol_trunc($newref, $maxlength,
'middle');
5763 'objecttype' => (isset($this->
type) ? ($this->
type == 1 ?
'service' :
'product') : $this->element),
5764 'option' => $option,
5767 $classfortooltip =
'classfortooltip';
5770 $classfortooltip =
'classforajaxtooltip';
5771 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
5778 if (empty($notooltip)) {
5780 $label = $langs->trans(
"ShowProduct");
5781 $linkclose .=
' alt="'.dol_escape_htmltag($label, 1, 1).
'"';
5783 $linkclose .= ($label ?
' title="'.dol_escape_htmltag($label, 1, 1).
'"' :
' title="tocomplete"');
5784 $linkclose .= $dataparams.
' class="nowraponall '.$classfortooltip.($morecss ?
' '.$morecss :
'').
'"';
5786 $linkclose =
' class="nowraponall'.($morecss ?
' '.$morecss :
'').
'"';
5789 if ($option ==
'supplier' || $option ==
'category') {
5790 $url = DOL_URL_ROOT.
'/product/price_suppliers.php?id='.$this->id;
5791 } elseif ($option ==
'stock') {
5792 $url = DOL_URL_ROOT.
'/product/stock/product.php?id='.$this->id;
5793 } elseif ($option ==
'composition') {
5794 $url = DOL_URL_ROOT.
'/product/composition/card.php?id='.$this->id;
5796 $url = DOL_URL_ROOT.
'/product/card.php?id='.$this->id;
5799 if ($option !==
'nolink') {
5801 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
5802 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
5803 $add_save_lastsearch_values = 1;
5805 if ($add_save_lastsearch_values) {
5806 $url .=
'&save_lastsearch_values=1';
5810 $linkstart =
'<a href="'.$url.
'"';
5811 $linkstart .= $linkclose.
'>';
5814 $result .= $linkstart;
5817 $result .= (
img_object(($notooltip ?
'' : $label),
'product',
'class="paddingright"', 0, 0, $notooltip ? 0 : 1));
5820 $result .= (
img_object(($notooltip ?
'' : $label),
'service',
'class="paddingright"', 0, 0, $notooltip ? 0 : 1));
5823 $result .=
'<span class="aaa">'.dol_escape_htmltag($newref).
'</span>';
5824 $result .= $linkend;
5825 if ($withpicto != 2) {
5826 $result .= (($add_label && $this->label) ? $sep.dol_trunc($this->label, ($add_label > 1 ? $add_label : 0)) :
'');
5830 $hookmanager->initHooks(array(
'productdao'));
5831 $parameters = array(
'id' => $this->
id,
'getnomurl' => &$result,
'label' => &$label);
5832 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
5834 $result = $hookmanager->resPrint;
5836 $result .= $hookmanager->resPrint;
5853 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
5857 $langs->load(
"products");
5858 $outputlangs->load(
"products");
5865 $modelpath =
"core/modules/product/doc/";
5867 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
5883 return $this->
LibStatut($this->status_buy, $mode, $type);
5885 return $this->
LibStatut($this->status_batch, $mode, $type);
5888 return $this->
LibStatut($this->status_buy, $mode, $type);
5906 $labelStatus = $labelStatusShort =
'';
5908 $langs->load(
'products');
5909 if (isModEnabled(
'productbatch')) {
5910 $langs->load(
"productbatch");
5916 $label = ($status == 0 ? $langs->transnoentitiesnoconv(
'ProductStatusNotOnBatch') : ($status == 1 ? $langs->transnoentitiesnoconv(
'ProductStatusOnBatch') : $langs->transnoentitiesnoconv(
'ProductStatusOnSerial')));
5917 return dolGetStatus($label);
5919 $label = ($status == 0 ? $langs->transnoentitiesnoconv(
'ProductStatusNotOnBatchShort') : ($status == 1 ? $langs->transnoentitiesnoconv(
'ProductStatusOnBatchShort') : $langs->transnoentitiesnoconv(
'ProductStatusOnSerialShort')));
5920 return dolGetStatus($label);
5924 return dolGetStatus($langs->transnoentitiesnoconv(
'ProductStatusNotOnBatch'),
'',
'', empty($status) ?
'status5' :
'status4', 3,
'dot');
5930 return dolGetStatus($langs->transnoentitiesnoconv(
'Unknown'));
5934 $statuttrans = empty($status) ?
'status5' :
'status4';
5939 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusNotOnSellShort');
5940 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusNotOnSell');
5941 } elseif ($type == 1) {
5942 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusNotOnBuyShort');
5943 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusNotOnBuy');
5944 } elseif ($type == 2) {
5945 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusNotOnBatch');
5946 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusNotOnBatchShort');
5948 } elseif ($status == 1) {
5951 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusOnSellShort');
5952 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusOnSell');
5953 } elseif ($type == 1) {
5954 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusOnBuyShort');
5955 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusOnBuy');
5956 } elseif ($type == 2) {
5957 $labelStatus = ($status == 1 ? $langs->transnoentitiesnoconv(
'ProductStatusOnBatch') : $langs->transnoentitiesnoconv(
'ProductStatusOnSerial'));
5958 $labelStatusShort = ($status == 1 ? $langs->transnoentitiesnoconv(
'ProductStatusOnBatchShort') : $langs->transnoentitiesnoconv(
'ProductStatusOnSerialShort'));
5960 } elseif ($type == 2 && $status == 2) {
5961 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusOnSerial');
5962 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusOnSerialShort');
5966 return dolGetStatus($langs->transnoentitiesnoconv(
'Unknown'),
'',
'',
'status0', 0);
5968 return dolGetStatus($labelStatus, $labelStatusShort,
'', $statuttrans, $mode);
5982 $langs->load(
'products');
5985 if (isset($this->finished) && $this->finished >= 0) {
5986 $sql =
"SELECT label, code FROM ".$this->db->prefix().
"c_product_nature where code = ".((int) $this->finished).
" AND active=1";
5987 $resql = $this->db->query($sql);
5989 $this->error = $this->db->error().
' sql='.$sql;
5990 dol_syslog(__METHOD__.
' Error '.$this->error, LOG_ERR);
5992 } elseif ($this->db->num_rows($resql) > 0 && $res = $this->db->fetch_array($resql)) {
5993 $label = $langs->trans($res[
'label']);
5995 $this->db->free($resql);
6019 public function correct_stock($user, $id_entrepot, $nbpiece, $movement, $label =
'', $price = 0, $inventorycode =
'', $origin_element =
'', $origin_id =
null, $disablestockchangeforsubproduct = 0, $extrafields =
null)
6025 include_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
6031 $nbpiece = abs($nbpiece);
6034 $op[0] =
"+".trim((
string) $nbpiece);
6035 $op[1] =
"-".trim((
string) $nbpiece);
6038 $movementstock->setOrigin($origin_element, $origin_id);
6039 $result = $movementstock->_create($user, $this->
id, $id_entrepot, $op[$movement], $movement, $price, $label, $inventorycode,
'',
'',
'',
'',
false, 0, $disablestockchangeforsubproduct);
6043 $array_options = $extrafields->getOptionalsFromPost(
'stock_mouvement');
6044 $movementstock->array_options = $array_options;
6045 $movementstock->insertExtraFields();
6047 $this->db->commit();
6050 $this->error = $movementstock->error;
6051 $this->errors = $movementstock->errors;
6053 $this->db->rollback();
6082 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)
6088 include_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
6094 $nbpiece = abs($nbpiece);
6098 $op[0] =
"+".trim((
string) $nbpiece);
6099 $op[1] =
"-".trim((
string) $nbpiece);
6102 $movementstock->setOrigin($origin_element, $origin_id);
6103 $result = $movementstock->_create($user, $this->
id, $id_entrepot, $op[$movement], $movement, $price, $label, $inventorycode,
'', $dlc, $dluo, $lot,
false, 0, $disablestockchangeforsubproduct, 0, $force_update_batch);
6107 $array_options = $extrafields->getOptionalsFromPost(
'stock_mouvement');
6108 $movementstock->array_options = $array_options;
6109 $movementstock->insertExtraFields();
6111 $this->db->commit();
6114 $this->error = $movementstock->error;
6115 $this->errors = $movementstock->errors;
6117 $this->db->rollback();
6137 public function load_stock($option =
'', $includedraftpoforvirtual =
null, $dateofvirtualstock =
null)
6140 $this->stock_reel = 0;
6141 $this->stock_warehouse = array();
6142 $this->stock_theorique = 0;
6145 $warehouseStatus = array();
6146 if (preg_match(
'/warehouseclosed/', $option)) {
6149 if (preg_match(
'/warehouseopen/', $option)) {
6152 if (preg_match(
'/warehouseinternal/', $option)) {
6160 $sql =
"SELECT ps.rowid, ps.reel, ps.fk_entrepot";
6161 $sql .=
" FROM ".$this->db->prefix().
"product_stock as ps";
6162 $sql .=
", ".$this->db->prefix().
"entrepot as w";
6163 $sql .=
" WHERE w.entity IN (".getEntity(
'stock').
")";
6164 $sql .=
" AND w.rowid = ps.fk_entrepot";
6165 $sql .=
" AND ps.fk_product = ".((int) $this->
id);
6166 if (count($warehouseStatus)) {
6167 $sql .=
" AND w.statut IN (".$this->db->sanitize(implode(
',', $warehouseStatus)).
")";
6170 $sql .=
" ORDER BY ps.reel ".(getDolGlobalString(
'DO_NOT_TRY_TO_DEFRAGMENT_STOCKS_WAREHOUSE') ?
'DESC' :
'ASC');
6172 dol_syslog(get_class($this).
"::load_stock", LOG_DEBUG);
6173 $result = $this->db->query($sql);
6175 $num = $this->db->num_rows($result);
6179 $row = $this->db->fetch_object($result);
6180 $this->stock_warehouse[$row->fk_entrepot] =
new stdClass();
6181 $this->stock_warehouse[$row->fk_entrepot]->real = $row->reel;
6182 $this->stock_warehouse[$row->fk_entrepot]->id = $row->rowid;
6183 if ((!preg_match(
'/nobatch/', $option)) && $this->
hasbatch()) {
6184 $this->stock_warehouse[$row->fk_entrepot]->detail_batch =
Productbatch::findAll($this->db, $row->rowid, 1, $this->id);
6186 $this->stock_reel += $row->reel;
6190 $this->db->free($result);
6192 if (!preg_match(
'/novirtual/', $option)) {
6198 $this->error = $this->db->lasterror();
6217 global $hookmanager, $action;
6219 $stock_commande_client = 0;
6220 $stock_commande_fournisseur = 0;
6221 $stock_sending_client = 0;
6222 $stock_reception_fournisseur = 0;
6223 $stock_inproduction = 0;
6227 if (isModEnabled(
'order')) {
6232 $stock_commande_client = $this->stats_commande[
'qty'];
6234 if (isModEnabled(
"shipping")) {
6235 require_once DOL_DOCUMENT_ROOT.
'/expedition/class/expedition.class.php';
6236 $filterShipmentStatus =
'';
6246 $stock_sending_client = $this->stats_expedition[
'qty'];
6249 if (isModEnabled(
"supplier_order")) {
6250 $filterStatus =
getDolGlobalString(
'SUPPLIER_ORDER_STATUS_FOR_VIRTUAL_STOCK',
'3,4');
6251 if (isset($includedraftpoforvirtual)) {
6252 $filterStatus =
'0,1,2,'.$filterStatus;
6258 $stock_commande_fournisseur = $this->stats_commande_fournisseur[
'qty'];
6261 if (isModEnabled(
"supplier_order") || isModEnabled(
"supplier_invoice")) {
6262 $filterStatus =
'4';
6263 if (isset($includedraftpoforvirtual)) {
6264 $filterStatus =
'0,'.$filterStatus;
6270 $stock_reception_fournisseur = $this->stats_reception[
'qty'];
6273 if (isModEnabled(
'mrp')) {
6278 $stock_inproduction = $this->stats_mrptoproduce[
'qty'] - $this->stats_mrptoconsume[
'qty'];
6281 $this->stock_theorique = $this->stock_reel + $stock_inproduction;
6285 $this->stock_theorique -= ($stock_commande_client - $stock_sending_client);
6287 $this->stock_theorique += 0;
6289 $this->stock_theorique -= $stock_commande_client;
6293 $this->stock_theorique += ($stock_commande_fournisseur - $stock_reception_fournisseur);
6295 $this->stock_theorique += ($stock_commande_fournisseur - $stock_reception_fournisseur);
6297 $this->stock_theorique -= $stock_reception_fournisseur;
6299 $this->stock_theorique += ($stock_commande_fournisseur - $stock_reception_fournisseur);
6302 $parameters = array(
'id' => $this->
id,
'includedraftpoforvirtual' => $includedraftpoforvirtual);
6304 $reshook = $hookmanager->executeHooks(
'loadvirtualstock', $parameters, $this, $action);
6306 $this->stock_theorique = $hookmanager->resArray[
'stock_theorique'];
6307 } elseif ($reshook == 0 && isset($hookmanager->resArray[
'stock_stats_hook'])) {
6308 $this->stock_theorique += $hookmanager->resArray[
'stock_stats_hook'];
6312 if (!empty($this->stock_warehouse) &&
getDolGlobalString(
'STOCK_ALLOW_VIRTUAL_STOCK_PER_WAREHOUSE')) {
6313 foreach ($this->stock_warehouse as $warehouseid => $stockwarehouse) {
6314 if (isModEnabled(
'mrp')) {
6321 if ($this->fk_default_warehouse == $warehouseid) {
6322 $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']);
6324 $this->stock_warehouse[$warehouseid]->virtual = $this->stock_warehouse[$warehouseid]->real + $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'];
6344 $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";
6345 $sql .=
" WHERE pb.fk_product_stock = ps.rowid AND ps.fk_product = ".((int) $this->
id).
" AND pb.batch = '".$this->db->escape($batch).
"'";
6346 $sql .=
" GROUP BY pb.batch, pb.eatby, pb.sellby";
6347 dol_syslog(get_class($this).
"::loadBatchInfo load first entry found for lot/serial = ".$batch, LOG_DEBUG);
6348 $resql = $this->db->query($sql);
6350 $num = $this->db->num_rows($resql);
6353 $obj = $this->db->fetch_object($resql);
6354 $result[] = array(
'batch' => $batch,
'eatby' => $this->db->jdate($obj->eatby),
'sellby' => $this->db->jdate($obj->sellby),
'qty' => $obj->qty);
6360 $this->db->rollback();
6377 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6383 $dir .=
'/'.get_exdir($this->
id, 2, 0, 0, $this,
'product').$this->id.
"/photos";
6385 $dir .=
'/'.get_exdir(0, 0, 0, 0, $this,
'product').dol_sanitizeFileName($this->
ref);
6390 $dir_osencoded = $dir;
6392 if (is_dir($dir_osencoded)) {
6393 $originImage = $dir.
'/'.$file[
'name'];
6404 if (is_numeric($result) && $result > 0) {
6421 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6422 include_once DOL_DOCUMENT_ROOT.
'/core/lib/images.lib.php';
6426 $dir .=
'/'.get_exdir($this->
id, 2, 0, 0, $this,
'product').$this->id.
"/photos/";
6428 $dir .=
'/'.get_exdir(0, 0, 0, 0, $this,
'product');
6432 if (file_exists($dir_osencoded)) {
6433 $handle = opendir($dir_osencoded);
6434 if (is_resource($handle)) {
6435 while (($file = readdir($handle)) !==
false) {
6437 $file = mb_convert_encoding($file,
'UTF-8',
'ISO-8859-1');
6460 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6461 include_once DOL_DOCUMENT_ROOT.
'/core/lib/images.lib.php';
6467 $handle = @opendir($dir_osencoded);
6468 if (is_resource($handle)) {
6469 while (($file = readdir($handle)) !==
false) {
6471 $file = mb_convert_encoding($file,
'UTF-8',
'ISO-8859-1');
6478 $photo_vignette =
'';
6480 if (preg_match(
'/('.$this->regeximgext.
')$/i', $photo, $regs)) {
6481 $photo_vignette = preg_replace(
'/'.$regs[0].
'/i',
'', $photo).
'_small'.$regs[0];
6484 $dirthumb = $dir.
'thumbs/';
6488 $obj[
'photo'] = $photo;
6489 if ($photo_vignette &&
dol_is_file($dirthumb.$photo_vignette)) {
6490 $obj[
'photo_vignette'] =
'thumbs/'.$photo_vignette;
6492 $obj[
'photo_vignette'] =
"";
6495 $tabobj[$nbphoto - 1] = $obj;
6498 if ($nbmax && $nbphoto >= $nbmax) {
6520 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6521 include_once DOL_DOCUMENT_ROOT.
'/core/lib/images.lib.php';
6523 $dir = dirname($file).
'/';
6524 $dirthumb = $dir.
'/thumbs/';
6525 $filename = preg_replace(
'/'.preg_quote($dir,
'/').
'/i',
'', $file);
6531 if (preg_match(
'/('.$this->regeximgext.
')$/i', $filename, $regs)) {
6532 $photo_vignette = preg_replace(
'/'.$regs[0].
'/i',
'', $filename).
'_small'.$regs[0];
6533 if (file_exists(
dol_osencode($dirthumb.$photo_vignette))) {
6537 $photo_vignette = preg_replace(
'/'.$regs[0].
'/i',
'', $filename).
'_mini'.$regs[0];
6538 if (file_exists(
dol_osencode($dirthumb.$photo_vignette))) {
6555 $infoImg = getimagesize($file_osencoded);
6556 $this->imgWidth = $infoImg[0];
6557 $this->imgHeight = $infoImg[1];
6567 global $hookmanager;
6569 $this->nb = array();
6571 $sql =
"SELECT count(p.rowid) as nb, fk_product_type";
6572 $sql .=
" FROM ".$this->db->prefix().
"product as p";
6573 $sql .=
' WHERE p.entity IN ('.getEntity($this->element, 1).
')';
6575 if (is_object($hookmanager)) {
6576 $parameters = array();
6577 $reshook = $hookmanager->executeHooks(
'printFieldListWhere', $parameters, $this);
6578 $sql .= $hookmanager->resPrint;
6580 $sql .=
' GROUP BY fk_product_type';
6582 $resql = $this->db->query($sql);
6584 while ($obj = $this->db->fetch_object($resql)) {
6585 if ($obj->fk_product_type == 1) {
6586 $this->nb[
"services"] = $obj->nb;
6588 $this->nb[
"products"] = $obj->nb;
6591 $this->db->free($resql);
6595 $this->error = $this->db->error();
6637 return $this->mandatory_period == 1;
6647 return $this->status_batch > 0;
6667 $dirsociete = array_merge(array(
'/core/modules/barcode/'), $conf->modules_parts[
'barcode']);
6668 foreach ($dirsociete as $dirroot) {
6676 '@phan-var-force ModeleNumRefBarCode $mod';
6678 $result = $mod->getNextValue(
$object, $type);
6680 dol_syslog(get_class($this).
"::get_barcode barcode=".$result.
" module=".$var);
6697 $this->specimen = 1;
6699 $this->
ref =
'PRODUCT_SPEC';
6700 $this->label =
'PRODUCT SPECIMEN';
6701 $this->
description =
'This is description of this product specimen that was created the '.dol_print_date($now,
'dayhourlog').
'.';
6702 $this->specimen = 1;
6703 $this->country_id = 1;
6705 $this->status_buy = 1;
6707 $this->sell_or_eat_by_mandatory = 0;
6708 $this->note_private =
'This is a comment (private)';
6709 $this->note_public =
'This is a comment (public)';
6710 $this->date_creation = $now;
6711 $this->date_modification = $now;
6714 $this->weight_units = 3;
6717 $this->length_units = 1;
6719 $this->width_units = 0;
6720 $this->height =
null;
6721 $this->height_units =
null;
6723 $this->surface = 30;
6724 $this->surface_units = 0;
6725 $this->volume = 300;
6726 $this->volume_units = 0;
6728 $this->barcode = -1;
6743 if (!$this->fk_unit) {
6747 $langs->load(
'products');
6749 $label_type =
'label';
6750 if ($type ==
'short') {
6751 $label_type =
'short_label';
6754 $sql =
"SELECT ".$label_type.
", code from ".$this->db->prefix().
"c_units where rowid = ".((int) $this->fk_unit);
6756 $resql = $this->db->query($sql);
6758 $this->error = $this->db->error();
6759 dol_syslog(get_class($this).
"::getLabelOfUnit Error ".$this->error, LOG_ERR);
6761 } elseif ($this->db->num_rows($resql) > 0 && $res = $this->db->fetch_array($resql)) {
6762 $label = ($label_type ==
'short_label' ? $res[$label_type] :
'unit'.$res[
'code']);
6764 $this->db->free($resql);
6778 $maxpricesupplier = 0;
6781 include_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
6783 $product_fourn_list = $product_fourn->list_product_fournisseur_price($this->
id,
'',
'');
6785 if (is_array($product_fourn_list) && count($product_fourn_list) > 0) {
6786 foreach ($product_fourn_list as $productfourn) {
6787 if ($productfourn->fourn_unitprice > $maxpricesupplier) {
6788 $maxpricesupplier = $productfourn->fourn_unitprice;
6796 return $maxpricesupplier;
6812 require_once DOL_DOCUMENT_ROOT.
'/categories/class/categorie.class.php';
6813 return parent::setCategoriesCommon($categories, Categorie::TYPE_PRODUCT);
6827 'product_customer_price',
6828 'product_customer_price_log'
6847 $sql =
"SELECT rowid, level, fk_level, var_percent, var_min_percent FROM ".$this->db->prefix().
"product_pricerules";
6848 $query = $this->db->query($sql);
6852 while ($result = $this->db->fetch_object($query)) {
6853 $rules[$result->level] = $result;
6862 for ($i = 1; $i <= $nbofproducts; $i++) {
6863 $price = $baseprice;
6864 $price_min = $baseprice;
6868 if ($i > 1 && isset($rules[$i]->var_percent) && $rules[$i]->var_percent) {
6869 $price = $prices[$rules[$i]->fk_level] * (1 + ($rules[$i]->var_percent / 100));
6872 $prices[$i] = $price;
6875 if (isset($rules[$i]->var_min_percent) && $rules[$i]->var_min_percent) {
6876 $price_min = $price * (1 - ($rules[$i]->var_min_percent / 100));
6880 $check_amount = (($price == $this->multiprices[$i]) && ($price_min == $this->multiprices_min[$i]));
6881 $check_type = ($baseprice == $this->multiprices_base_type[$i]);
6883 if ($check_amount && $check_type) {
6887 if ($this->
updatePrice($price, $price_type, $user, $price_vat, $price_min, $i, $npr, $psq, 1) < 0) {
6905 return $user->rights->produit;
6907 return $user->rights->service;
6919 $sql =
"SELECT p.rowid, p.ref, p.datec as date_creation, p.tms as date_modification,";
6920 $sql .=
" p.fk_user_author, p.fk_user_modif";
6921 $sql .=
" FROM ".$this->db->prefix().$this->table_element.
" as p";
6922 $sql .=
" WHERE p.rowid = ".((int) $id);
6924 $result = $this->db->query($sql);
6926 if ($this->db->num_rows($result)) {
6927 $obj = $this->db->fetch_object($result);
6929 $this->
id = $obj->rowid;
6930 $this->
ref = $obj->ref;
6932 $this->user_creation_id = $obj->fk_user_author;
6933 $this->user_modification_id = $obj->fk_user_modif;
6935 $this->date_creation = $this->db->jdate($obj->date_creation);
6936 $this->date_modification = $this->db->jdate($obj->date_modification);
6939 $this->db->free($result);
6953 if (empty($this->duration_value)) {
6954 $this->errors[] =
'ErrorDurationForServiceNotDefinedCantCalculateHourlyPrice';
6958 if ($this->duration_unit ==
'i') {
6959 $prodDurationHours = 1. / 60;
6961 if ($this->duration_unit ==
'h') {
6962 $prodDurationHours = 1.;
6964 if ($this->duration_unit ==
'd') {
6965 $prodDurationHours = 24.;
6967 if ($this->duration_unit ==
'w') {
6968 $prodDurationHours = 24. * 7;
6970 if ($this->duration_unit ==
'm') {
6971 $prodDurationHours = 24. * 30;
6973 if ($this->duration_unit ==
'y') {
6974 $prodDurationHours = 24. * 365;
6976 $prodDurationHours *= $this->duration_value;
6978 return $prodDurationHours;
6991 global $langs, $conf;
6993 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
6995 $return =
'<div class="box-flex-item box-flex-grow-zero">';
6996 $return .=
'<div class="info-box info-box-sm">';
6997 $return .=
'<div class="info-box-img">';
7000 $label .= $this->
show_photos(
'product', $conf->product->multidir_output[$this->entity], 1, 1, 0, 0, 0, 120, 160, 0, 0, 0,
'',
'photoref photokanban');
7010 $return .=
'</div>';
7011 $return .=
'<div class="info-box-content">';
7012 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this,
'getNomUrl') ? $this->
getNomUrl() : $this->ref).
'</span>';
7013 if ($selected >= 0) {
7014 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
7016 if (property_exists($this,
'label')) {
7017 $return .=
'<br><span class="info-box-label opacitymedium inline-block tdoverflowmax150 valignmiddle" title="'.dol_escape_htmltag($this->label).
'">'.
dol_escape_htmltag($this->label).
'</span>';
7019 if (property_exists($this,
'price') && property_exists($this,
'price_ttc')) {
7020 if ($this->price_base_type ==
'TTC') {
7021 $return .=
'<br><span class="info-box-status amount">'.price($this->price_ttc).
' '.$langs->trans(
"TTC").
'</span>';
7024 $return .=
'<br><span class="info-box-status amount">'.price($this->
price).
' '.$langs->trans(
"HT").
'</span>';
7029 if (property_exists($this,
'stock_reel') && $this->
isProduct()) {
7030 $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>';
7033 if (method_exists($this,
'getLibStatut')) {
7035 $return .=
'<br><div class="info-box-status inline-block valignmiddle">'.$this->getLibStatut(3, 1).
' '.$this->
getLibStatut(3, 0).
'</div>';
7037 $return .=
'<div class="info-box-status inline-block valignmiddle marginleftonly paddingleft">'.$this->getLibStatut(3, 1).
' '.$this->
getLibStatut(3, 0).
'</div>';
7040 $return .=
'</div>';
7041 $return .=
'</div>';
7042 $return .=
'</div>';
7055 if (!is_numeric($limit)) {
7059 $sql =
"SELECT p.rowid, p.ref, p.label, p.description, p.entity, ef.filename
7060 FROM ".MAIN_DB_PREFIX.
"product AS p
7061 JOIN ".MAIN_DB_PREFIX.
"ecm_files AS ef ON p.rowid = ef.src_object_id
7062 WHERE ef.entity IN (".
getEntity(
'product').
")
7063 AND (ef.filename LIKE '%.png' OR ef.filename LIKE '%.jpeg' OR ef.filename LIKE '%.svg')
7064 GROUP BY p.rowid, p.ref, p.label, p.description, p.entity, ef.filename
7065 ORDER BY p.datec ASC
7066 LIMIT " . ((int) $limit);
7068 $resql = $this->db->query($sql);
7069 $products = array();
7072 while ($obj = $this->db->fetch_object($resql)) {
7073 $products[] = array(
7074 'rowid' => $obj->rowid,
7076 'label' => $obj->label,
7077 'description' => $obj->description,
7078 'entity' => $obj->entity,
7079 'filename' => $obj->filename
7085 if (empty($products)) {
7098 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)
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.
Class to manage ECM files.
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.
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 the object is managed in stock.
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.
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 the object is a service.
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)
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.
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.
getProductsToPreviewInEmail($limit)
Retrieve and display products.
load_stats_facture($socid=0)
Charge tableau des stats facture pour le produit/service.
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.
load_stats_bom($socid=0)
Charge tableau des stats OF pour le produit/service.
hasbatch()
Return if the object has a sell-by or eat-by date.
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 clickable 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.
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)
getSellOrEatByMandatoryLabel()
Get sell or eat by mandatory label.
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.
load_stats_commande_fournisseur($socid=0, $filtrestatut='', $forVirtualStock=0, $dateofvirtualstock=null)
Charge tableau des stats commande fournisseur pour le produit/service.
isMandatoryPeriod()
Return if the object has a constraint on mandatory_period.
isProduct()
Return if the 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.
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
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 a 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