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';
77 protected $childtables = array(
78 'supplier_proposaldet' => array(
'name' =>
'SupplierProposal',
'parent' =>
'supplier_proposal',
'parentkey' =>
'fk_supplier_proposal'),
79 'propaldet' => array(
'name' =>
'Proposal',
'parent' =>
'propal',
'parentkey' =>
'fk_propal'),
80 'commandedet' => array(
'name' =>
'Order',
'parent' =>
'commande',
'parentkey' =>
'fk_commande'),
81 'facturedet' => array(
'name' =>
'Invoice',
'parent' =>
'facture',
'parentkey' =>
'fk_facture'),
82 'contratdet' => array(
'name' =>
'Contract',
'parent' =>
'contrat',
'parentkey' =>
'fk_contrat'),
83 'facture_fourn_det' => array(
'name' =>
'SupplierInvoice',
'parent' =>
'facture_fourn',
'parentkey' =>
'fk_facture_fourn'),
84 'commande_fournisseurdet' => array(
'name' =>
'SupplierOrder',
'parent' =>
'commande_fournisseur',
'parentkey' =>
'fk_commande'),
85 'mrp_production' => array(
'name' =>
'Mo',
'parent' =>
'mrp_mo',
'parentkey' =>
'fk_mo',
'enabled' =>
'isModEnabled("mrp")'),
86 'bom_bom' => array(
'name' =>
'BOM',
'enabled' =>
'isModEnabled("bom")'),
87 'bom_bomline' => array(
'name' =>
'BOMLine',
'parent' =>
'bom_bom',
'parentkey' =>
'fk_bom',
'enabled' =>
'isModEnabled("bom")'),
95 public $picto =
'product';
106 public $regeximgext =
'\.gif|\.jpg|\.jpeg|\.png|\.bmp|\.webp|\.xpm|\.xbm';
153 public $price_formated;
165 public $price_ttc_formated;
179 public $price_min_ttc;
185 public $price_base_type;
195 public $multiprices = array();
199 public $multiprices_ttc = array();
203 public $multiprices_base_type = array();
207 public $multiprices_default_vat_code = array();
211 public $multiprices_min = array();
215 public $multiprices_min_ttc = array();
219 public $multiprices_tva_tx = array();
223 public $multiprices_recuperableonly = array();
229 public $price_by_qty;
233 public $prices_by_qty = array();
237 public $prices_by_qty_id = array();
241 public $prices_by_qty_list = array();
251 public $multilangs = array();
256 public $default_vat_code;
271 public $remise_percent;
276 public $localtax1_tx;
280 public $localtax2_tx;
284 public $localtax1_type;
288 public $localtax2_type;
295 public $desc_supplier;
299 public $vatrate_supplier;
303 public $default_vat_code_supplier;
308 public $fourn_multicurrency_price;
312 public $fourn_multicurrency_unitprice;
316 public $fourn_multicurrency_tx;
320 public $fourn_multicurrency_id;
324 public $fourn_multicurrency_code;
346 public $qc_frequency;
353 public $stock_reel = 0;
360 public $stock_theorique;
379 public $seuil_stock_alerte = 0;
384 public $desiredstock = 0;
389 public $duration_value;
393 public $duration_unit;
402 public $fk_default_workstation;
424 public $status_buy = 0;
446 public $fk_default_bom;
453 public $product_fourn_price_id;
475 public $status_batch = 0;
482 public $sell_or_eat_by_mandatory = 0;
489 public $batch_mask =
'';
514 public $weight_units;
522 public $length_units;
538 public $height_units;
546 public $surface_units;
554 public $volume_units;
563 public $net_measure_units;
568 public $accountancy_code_sell;
572 public $accountancy_code_sell_intra;
576 public $accountancy_code_sell_export;
580 public $accountancy_code_buy;
584 public $accountancy_code_buy_intra;
588 public $accountancy_code_buy_export;
598 public $barcode_type;
603 public $barcode_type_code;
608 public $stats_propale = array();
613 public $stats_commande = array();
618 public $stats_contrat = array();
623 public $stats_facture = array();
628 public $stats_proposal_supplier = array();
633 public $stats_commande_fournisseur = array();
638 public $stats_expedition = array();
643 public $stats_reception = array();
648 public $stats_mo = array();
653 public $stats_bom = array();
658 public $stats_mrptoconsume = array();
663 public $stats_mrptoproduce = array();
668 public $stats_facturerec = array();
673 public $stats_facture_fournisseur = array();
688 public $product_fourn_id;
694 public $product_id_already_linked;
705 public $stock_warehouse = array();
710 public $fk_default_warehouse;
715 public $fk_price_expression;
733 public $fourn_price_base_type;
750 public $ref_supplier;
764 public $price_autogen = 0;
771 public $supplierprices;
791 public $is_object_used;
802 public $is_sousproduit_qty;
814 public $is_sousproduit_incdec;
819 public $mandatory_period;
850 public $fields = array(
851 'rowid' => array(
'type' =>
'integer',
'label' =>
'TechnicalID',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'index' => 1,
'position' => 1,
'comment' =>
'Id'),
852 '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'),
853 'entity' => array(
'type' =>
'integer',
'label' =>
'Entity',
'enabled' => 1,
'visible' => 0,
'default' =>
'1',
'notnull' => 1,
'index' => 1,
'position' => 5),
854 'label' => array(
'type' =>
'varchar(255)',
'label' =>
'Label',
'enabled' => 1,
'visible' => 1,
'notnull' => 1,
'showoncombobox' => 2,
'position' => 15,
'csslist' =>
'tdoverflowmax250'),
855 'barcode' => array(
'type' =>
'varchar(255)',
'label' =>
'Barcode',
'enabled' =>
'isModEnabled("barcode")',
'position' => 20,
'visible' => -1,
'showoncombobox' => 3,
'cssview' =>
'tdwordbreak',
'csslist' =>
'tdoverflowmax125'),
856 'fk_barcode_type' => array(
'type' =>
'integer',
'label' =>
'BarcodeType',
'enabled' => 1,
'position' => 21,
'notnull' => 0,
'visible' => -1,),
857 'note_public' => array(
'type' =>
'html',
'label' =>
'NotePublic',
'enabled' => 1,
'visible' => 0,
'position' => 61),
858 'note' => array(
'type' =>
'html',
'label' =>
'NotePrivate',
'enabled' => 1,
'visible' => 0,
'position' => 62),
859 'datec' => array(
'type' =>
'datetime',
'label' =>
'DateCreation',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 500),
860 'tms' => array(
'type' =>
'timestamp',
'label' =>
'DateModification',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 501),
862 'fk_user_author' => array(
'type' =>
'integer',
'label' =>
'UserAuthor',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 510,
'foreignkey' =>
'llx_user.rowid'),
863 'fk_user_modif' => array(
'type' =>
'integer',
'label' =>
'UserModif',
'enabled' => 1,
'visible' => -2,
'notnull' => -1,
'position' => 511),
865 'localtax1_tx' => array(
'type' =>
'double(6,3)',
'label' =>
'Localtax1tx',
'enabled' => 1,
'position' => 150,
'notnull' => 0,
'visible' => -1,),
866 'localtax1_type' => array(
'type' =>
'varchar(10)',
'label' =>
'Localtax1type',
'enabled' => 1,
'position' => 155,
'notnull' => 1,
'visible' => -1,),
867 'localtax2_tx' => array(
'type' =>
'double(6,3)',
'label' =>
'Localtax2tx',
'enabled' => 1,
'position' => 160,
'notnull' => 0,
'visible' => -1,),
868 'localtax2_type' => array(
'type' =>
'varchar(10)',
'label' =>
'Localtax2type',
'enabled' => 1,
'position' => 165,
'notnull' => 1,
'visible' => -1,),
869 'last_main_doc' => array(
'type' =>
'varchar(255)',
'label' =>
'LastMainDoc',
'enabled' => 1,
'visible' => -1,
'position' => 170),
870 'import_key' => array(
'type' =>
'varchar(14)',
'label' =>
'ImportId',
'enabled' => 1,
'visible' => -2,
'notnull' => -1,
'index' => 0,
'position' => 1000),
873 'mandatory_period' => array(
'type' =>
'integer',
'label' =>
'mandatoryperiod',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'default' =>
'0',
'index' => 1,
'position' => 1000),
894 $this->ismultientitymanaged = 1;
895 $this->isextrafieldmanaged = 1;
908 $this->
ref = trim($this->
ref);
936 public function create($user, $notrigger = 0)
938 global
$conf, $langs;
944 $this->
ref = trim($this->
ref);
948 $this->label = trim($this->label);
949 $this->price_ttc = (float)
price2num($this->price_ttc);
951 $this->price_min_ttc = (float)
price2num($this->price_min_ttc);
952 $this->price_min = (float)
price2num($this->price_min);
953 $this->price_label = trim($this->price_label);
954 if (empty($this->tva_tx)) {
957 if (empty($this->tva_npr)) {
961 if (empty($this->localtax1_tx)) {
962 $this->localtax1_tx = 0;
964 if (empty($this->localtax2_tx)) {
965 $this->localtax2_tx = 0;
967 if (empty($this->localtax1_type)) {
968 $this->localtax1_type =
'0';
970 if (empty($this->localtax2_type)) {
971 $this->localtax2_type =
'0';
973 if (empty($this->
price)) {
976 if (empty($this->price_min)) {
977 $this->price_min = 0;
980 if (empty($this->price_by_qty)) {
981 $this->price_by_qty = 0;
984 if (empty($this->
status)) {
987 if (empty($this->status_buy)) {
988 $this->status_buy = 0;
997 if ($this->price_base_type ==
'TTC' && $this->price_ttc > 0) {
998 $price_ttc =
price2num($this->price_ttc,
'MU');
999 $price_ht =
price2num($this->price_ttc / (1 + ($this->tva_tx / 100)),
'MU');
1003 if ($this->price_base_type !=
'TTC' && $this->
price > 0) {
1005 $price_ttc =
price2num($this->
price * (1 + ($this->tva_tx / 100)),
'MU');
1009 if (($this->price_min_ttc > 0) && ($this->price_base_type ==
'TTC')) {
1010 $price_min_ttc =
price2num($this->price_min_ttc,
'MU');
1011 $price_min_ht =
price2num($this->price_min_ttc / (1 + ($this->tva_tx / 100)),
'MU');
1015 if (($this->price_min > 0) && ($this->price_base_type !=
'TTC')) {
1016 $price_min_ht =
price2num($this->price_min,
'MU');
1017 $price_min_ttc =
price2num($this->price_min * (1 + ($this->tva_tx / 100)),
'MU');
1020 $this->accountancy_code_buy = trim($this->accountancy_code_buy);
1021 $this->accountancy_code_buy_intra = trim($this->accountancy_code_buy_intra);
1022 $this->accountancy_code_buy_export = trim($this->accountancy_code_buy_export);
1023 $this->accountancy_code_sell = trim($this->accountancy_code_sell);
1024 $this->accountancy_code_sell_intra = trim($this->accountancy_code_sell_intra);
1025 $this->accountancy_code_sell_export = trim($this->accountancy_code_sell_export);
1028 $this->barcode = trim($this->barcode);
1029 $this->mandatory_period = empty($this->mandatory_period) ? 0 : $this->mandatory_period;
1031 if (empty($this->label)) {
1032 $this->error =
'ErrorMandatoryParametersNotProvided';
1036 if (empty($this->
ref) || $this->
ref ==
'auto') {
1038 $module =
getDolGlobalString(
'PRODUCT_CODEPRODUCT_ADDON',
'mod_codeproduct_leopard');
1039 if ($module !=
'mod_codeproduct_leopard') {
1040 if (substr($module, 0, 16) ==
'mod_codeproduct_' && substr($module, -3) ==
'php') {
1041 $module = substr($module, 0,
dol_strlen($module) - 4);
1044 $modCodeProduct =
new $module();
1045 '@phan-var-force ModeleProductCode $modCodeProduct';
1046 if (!empty($modCodeProduct->code_auto)) {
1047 $this->
ref = $modCodeProduct->getNextValue($this, $this->
type);
1049 unset($modCodeProduct);
1052 if (empty($this->
ref)) {
1053 $this->error =
'ProductModuleNotSetupForAutoRef';
1058 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);
1062 if (empty($this->date_creation)) {
1063 $this->date_creation = $now;
1069 if ($this->barcode ==
'-1' || $this->barcode ==
'auto') {
1070 $this->barcode = $this->
get_barcode($this, $this->barcode_type_code);
1075 $result = $this->
verify();
1078 $sql =
"SELECT count(*) as nb";
1079 $sql .=
" FROM ".$this->db->prefix().
"product";
1080 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
1081 $sql .=
" AND ref = '".$this->db->escape($this->
ref).
"'";
1083 $result = $this->db->query($sql);
1085 $obj = $this->db->fetch_object($result);
1086 if ($obj->nb == 0) {
1088 $sql =
"INSERT INTO ".$this->db->prefix().
"product (";
1092 $sql .=
", ref_ext";
1093 $sql .=
", price_min";
1094 $sql .=
", price_min_ttc";
1096 $sql .=
", fk_user_author";
1097 $sql .=
", fk_product_type";
1099 $sql .=
", price_ttc";
1100 $sql .=
", price_base_type";
1101 $sql .=
", price_label";
1105 $sql .=
", accountancy_code_buy";
1106 $sql .=
", accountancy_code_buy_intra";
1107 $sql .=
", accountancy_code_buy_export";
1108 $sql .=
", accountancy_code_sell";
1109 $sql .=
", accountancy_code_sell_intra";
1110 $sql .=
", accountancy_code_sell_export";
1113 $sql .=
", finished";
1114 $sql .=
", tobatch";
1115 $sql .=
", sell_or_eat_by_mandatory";
1116 $sql .=
", batch_mask";
1117 $sql .=
", fk_unit";
1118 $sql .=
", mandatory_period";
1119 $sql .=
") VALUES (";
1120 $sql .=
"'".$this->db->idate($this->date_creation).
"'";
1121 $sql .=
", ".(!empty($this->entity) ? (int) $this->entity : (int)
$conf->entity);
1122 $sql .=
", '".$this->db->escape($this->
ref).
"'";
1123 $sql .=
", ".(!empty($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
1124 $sql .=
", ".price2num($price_min_ht);
1125 $sql .=
", ".price2num($price_min_ttc);
1126 $sql .=
", ".(!empty($this->label) ?
"'".$this->db->escape($this->label).
"'" :
"null");
1127 $sql .=
", ".((int) $user->id);
1128 $sql .=
", ".((int) $this->
type);
1129 $sql .=
", ".price2num($price_ht,
'MT');
1130 $sql .=
", ".price2num($price_ttc,
'MT');
1131 $sql .=
", '".$this->db->escape($this->price_base_type).
"'";
1132 $sql .=
", ".(!empty($this->price_label) ?
"'".$this->db->escape($this->price_label).
"'" :
"null");
1133 $sql .=
", ".((int) $this->
status);
1134 $sql .=
", ".((int) $this->status_buy);
1136 $sql .=
", '".$this->db->escape($this->accountancy_code_buy).
"'";
1137 $sql .=
", '".$this->db->escape($this->accountancy_code_buy_intra).
"'";
1138 $sql .=
", '".$this->db->escape($this->accountancy_code_buy_export).
"'";
1139 $sql .=
", '".$this->db->escape($this->accountancy_code_sell).
"'";
1140 $sql .=
", '".$this->db->escape($this->accountancy_code_sell_intra).
"'";
1141 $sql .=
", '".$this->db->escape($this->accountancy_code_sell_export).
"'";
1143 $sql .=
", '".$this->db->escape($this->canvas).
"'";
1144 $sql .=
", ".((!isset($this->finished) || $this->finished < 0 || $this->finished ==
'') ?
'NULL' : (int) $this->finished);
1145 $sql .=
", ".((empty($this->status_batch) || $this->status_batch < 0) ?
'0' : ((int) $this->status_batch));
1146 $sql .=
", ".((empty($this->sell_or_eat_by_mandatory) || $this->sell_or_eat_by_mandatory < 0) ? 0 : ((int) $this->sell_or_eat_by_mandatory));
1147 $sql .=
", '".$this->db->escape($this->batch_mask).
"'";
1148 $sql .=
", ".($this->fk_unit > 0 ? ((int) $this->fk_unit) :
'NULL');
1149 $sql .=
", '".$this->db->escape($this->mandatory_period).
"'";
1152 dol_syslog(get_class($this).
"::Create", LOG_DEBUG);
1154 $result = $this->db->query($sql);
1156 $id = $this->db->last_insert_id($this->db->prefix().
"product");
1160 $this->
price = $price_ht;
1161 $this->price_ttc = $price_ttc;
1162 $this->price_min = $price_min_ht;
1163 $this->price_min_ttc = $price_min_ttc;
1167 if ($this->
update($id, $user, 1,
'add') <= 0) {
1172 $this->error = $this->db->lasterror();
1177 $this->db->query(
"DELETE FROM " . $this->db->prefix() .
"product_perentity WHERE fk_product = " .((int) $this->id) .
" AND entity = " . ((
int)
$conf->entity));
1179 $sql =
"INSERT INTO " . $this->db->prefix() .
"product_perentity (";
1180 $sql .=
" fk_product";
1182 $sql .=
", accountancy_code_buy";
1183 $sql .=
", accountancy_code_buy_intra";
1184 $sql .=
", accountancy_code_buy_export";
1185 $sql .=
", accountancy_code_sell";
1186 $sql .=
", accountancy_code_sell_intra";
1187 $sql .=
", accountancy_code_sell_export";
1188 $sql .=
") VALUES (";
1190 $sql .=
", " . ((int)
$conf->entity);
1191 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy) .
"'";
1192 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_intra) .
"'";
1193 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_export) .
"'";
1194 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell) .
"'";
1195 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_intra) .
"'";
1196 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_export) .
"'";
1198 $result = $this->db->query($sql);
1201 $this->error =
'ErrorFailedToInsertAccountancyForEntity';
1206 $this->error =
'ErrorFailedToGetInsertedId';
1210 $this->error = $this->db->lasterror();
1214 $langs->load(
"products");
1216 $this->error =
"ErrorProductAlreadyExists";
1217 dol_syslog(get_class($this).
"::Create fails, ref ".$this->
ref.
" already exists");
1221 $this->error = $this->db->lasterror();
1224 if (!$error && !$notrigger) {
1226 $result = $this->
call_trigger(
'PRODUCT_CREATE', $user);
1234 $this->db->commit();
1237 $this->db->rollback();
1241 $this->db->rollback();
1242 dol_syslog(get_class($this).
"::Create fails verify ".implode(
',', $this->errors), LOG_WARNING);
1258 $this->errors = array();
1261 $this->
ref = trim($this->
ref);
1264 $this->errors[] =
'ErrorBadRef';
1268 $arrayofnonnegativevalue = array(
'weight' =>
'Weight',
'width' =>
'Width',
'height' =>
'Height',
'length' =>
'Length',
'surface' =>
'Surface',
'volume' =>
'Volume');
1269 foreach ($arrayofnonnegativevalue as $key => $value) {
1270 if (property_exists($this, $key) && !empty($this->$key) && ($this->$key < 0)) {
1271 $langs->loadLangs(array(
"main",
"other"));
1272 $this->error = $langs->trans(
"FieldCannotBeNegative", $langs->transnoentitiesnoconv($value));
1273 $this->errors[] = $this->error;
1278 $rescode = $this->
check_barcode($this->barcode, $this->barcode_type_code);
1280 if ($rescode == -1) {
1281 $this->errors[] =
'ErrorBadBarCodeSyntax';
1282 } elseif ($rescode == -2) {
1283 $this->errors[] =
'ErrorBarCodeRequired';
1284 } elseif ($rescode == -3) {
1286 $this->errors[] =
'ErrorBarCodeAlreadyUsed';
1314 $dirsociete = array_merge(array(
'/core/modules/barcode/'),
$conf->modules_parts[
'barcode']);
1315 foreach ($dirsociete as $dirroot) {
1322 $mod =
new $module();
1323 '@phan-var-force ModeleNumRefBarCode $mod';
1325 dol_syslog(get_class($this).
"::check_barcode value=".$valuetotest.
" type=".$typefortest.
" module=".$module);
1326 $result = $mod->verif($this->db, $valuetotest, $this, 0, $typefortest);
1344 public function update($id, $user, $notrigger = 0, $action =
'update', $updatetype =
false)
1346 global $langs,
$conf, $hookmanager;
1351 if (!$this->label) {
1352 $this->label =
'MISSING LABEL';
1357 $this->
ref = trim($this->
ref);
1361 $this->label = trim($this->label);
1363 $this->note_private = (isset($this->note_private) ? trim($this->note_private) :
null);
1364 $this->note_public = (isset($this->note_public) ? trim($this->note_public) :
null);
1365 $this->net_measure =
price2num($this->net_measure);
1366 $this->net_measure_units = (empty($this->net_measure_units) ?
'' : trim((
string) $this->net_measure_units));
1367 $this->weight =
price2num($this->weight);
1368 $this->weight_units = (empty($this->weight_units) ?
'' : trim((
string) $this->weight_units));
1369 $this->length =
price2num($this->length);
1370 $this->length_units = (empty($this->length_units) ?
'' : trim((
string) $this->length_units));
1372 $this->width_units = (empty($this->width_units) ?
'' : trim((
string) $this->width_units));
1373 $this->height =
price2num($this->height);
1374 $this->height_units = (empty($this->height_units) ?
'' : trim((
string) $this->height_units));
1375 $this->surface =
price2num($this->surface);
1376 $this->surface_units = (empty($this->surface_units) ?
'' : trim((
string) $this->surface_units));
1377 $this->volume =
price2num($this->volume);
1378 $this->volume_units = (empty($this->volume_units) ?
'' : trim((
string) $this->volume_units));
1381 if (is_numeric($this->length_units)) {
1382 $this->width_units = $this->length_units;
1384 if (is_numeric($this->length_units)) {
1385 $this->height_units = $this->length_units;
1389 if (empty($this->surface) && !empty($this->length) && !empty($this->width) && $this->length_units == $this->width_units) {
1390 $this->surface = (float) $this->length * (
float) $this->width;
1393 if (empty($this->volume) && !empty($this->surface) && !empty($this->height) && $this->length_units == $this->height_units) {
1394 $this->volume = $this->surface * (float) $this->height;
1398 if (empty($this->tva_tx)) {
1401 if (empty($this->tva_npr)) {
1404 if (empty($this->localtax1_tx)) {
1405 $this->localtax1_tx = 0;
1407 if (empty($this->localtax2_tx)) {
1408 $this->localtax2_tx = 0;
1410 if (empty($this->localtax1_type)) {
1411 $this->localtax1_type =
'0';
1413 if (empty($this->localtax2_type)) {
1414 $this->localtax2_type =
'0';
1416 if (empty($this->
status)) {
1419 if (empty($this->status_buy)) {
1420 $this->status_buy = 0;
1423 if (empty($this->country_id)) {
1424 $this->country_id = 0;
1427 if (empty($this->state_id)) {
1428 $this->state_id = 0;
1432 $this->barcode = (empty($this->barcode) ?
'' : trim($this->barcode));
1434 $this->accountancy_code_buy = trim($this->accountancy_code_buy);
1435 $this->accountancy_code_buy_intra = (!empty($this->accountancy_code_buy_intra) ? trim($this->accountancy_code_buy_intra) :
'');
1436 $this->accountancy_code_buy_export = trim($this->accountancy_code_buy_export);
1437 $this->accountancy_code_sell = trim($this->accountancy_code_sell);
1438 $this->accountancy_code_sell_intra = trim($this->accountancy_code_sell_intra);
1439 $this->accountancy_code_sell_export = trim($this->accountancy_code_sell_export);
1446 if ($action !=
'add') {
1447 $result = $this->
verify();
1455 if (is_null($this->oldcopy) || (is_object($this->oldcopy) && $this->oldcopy->isEmpty())) {
1460 if ($this->
hasbatch() && !$this->oldcopy->hasbatch()) {
1462 $valueforundefinedlot =
'000000';
1467 dol_syslog(
"Flag batch of product id=".$this->
id.
" is set to ON, so we will create missing records into product_batch");
1470 foreach ($this->stock_warehouse as $idW => $ObjW) {
1472 foreach ($ObjW->detail_batch as $detail) {
1473 if ($detail->batch == $valueforundefinedlot || $detail->batch ==
'Undefined') {
1475 $sqlclean =
"DELETE FROM ".$this->db->prefix().
"product_batch WHERE batch in('Undefined', '".$this->db->escape($valueforundefinedlot).
"') AND fk_product_stock = ".((int) $ObjW->id);
1476 $result = $this->db->query($sqlclean);
1484 $qty_batch += $detail->qty;
1488 if ($ObjW->real != $qty_batch) {
1490 $ObjBatch->batch = $valueforundefinedlot;
1491 $ObjBatch->qty = ($ObjW->real - $qty_batch);
1492 $ObjBatch->fk_product_stock = (int) $ObjW->id;
1494 if ($ObjBatch->create($user, 1) < 0) {
1496 $this->errors = $ObjBatch->errors;
1501 if ($ObjLot->fetch(0, $this->id, $valueforundefinedlot) == 0) {
1502 $ObjLot->fk_product = $this->id;
1503 $ObjLot->entity = $this->entity;
1504 $ObjLot->fk_user_creat = $user->id;
1505 $ObjLot->batch = $valueforundefinedlot;
1506 if ($ObjLot->create($user,
true) < 0) {
1508 $this->errors = $ObjLot->errors;
1517 if ($this->barcode == -1) {
1518 $this->barcode = $this->
get_barcode($this, $this->barcode_type_code);
1521 $sql =
"UPDATE ".$this->db->prefix().
"product";
1522 $sql .=
" SET label = '".$this->db->escape($this->label).
"'";
1525 $sql .=
", fk_product_type = ".((int) $this->
type);
1528 $sql .=
", ref = '".$this->db->escape($this->
ref).
"'";
1529 $sql .=
", ref_ext = ".(!empty($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
1530 $sql .=
", default_vat_code = ".($this->default_vat_code ?
"'".$this->db->escape($this->default_vat_code).
"'" :
"null");
1531 $sql .=
", tva_tx = ".((float) $this->tva_tx);
1532 $sql .=
", recuperableonly = ".((int) $this->tva_npr);
1533 $sql .=
", localtax1_tx = ".((float) $this->localtax1_tx);
1534 $sql .=
", localtax2_tx = ".((float) $this->localtax2_tx);
1535 $sql .=
", localtax1_type = ".($this->localtax1_type !=
'' ?
"'".$this->db->escape($this->localtax1_type).
"'" :
"'0'");
1536 $sql .=
", localtax2_type = ".($this->localtax2_type !=
'' ?
"'".$this->db->escape($this->localtax2_type).
"'" :
"'0'");
1538 $sql .=
", barcode = ".(empty($this->barcode) ?
"null" :
"'".$this->db->escape($this->barcode).
"'");
1539 $sql .=
", fk_barcode_type = ".(empty($this->barcode_type) ?
"null" : $this->db->escape($this->barcode_type));
1541 $sql .=
", tosell = ".(int) $this->
status;
1542 $sql .=
", tobuy = ".(int) $this->status_buy;
1543 $sql .=
", tobatch = ".((empty($this->status_batch) || $this->status_batch < 0) ?
'0' : (int) $this->status_batch);
1544 $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);
1545 $sql .=
", batch_mask = '".$this->db->escape($this->batch_mask).
"'";
1547 $sql .=
", finished = ".((!isset($this->finished) || $this->finished < 0 || $this->finished ===
'') ?
"null" : (int) $this->finished);
1548 $sql .=
", fk_default_bom = ".((!isset($this->fk_default_bom) || $this->fk_default_bom < 0 || $this->fk_default_bom ==
'') ?
"null" : (int) $this->fk_default_bom);
1549 $sql .=
", net_measure = ".($this->net_measure !=
'' ?
"'".$this->db->escape($this->net_measure).
"'" :
'null');
1550 $sql .=
", net_measure_units = ".($this->net_measure_units !=
'' ?
"'".$this->db->escape($this->net_measure_units).
"'" :
'null');
1551 $sql .=
", weight = ".($this->weight !=
'' ?
"'".$this->db->escape($this->weight).
"'" :
'null');
1552 $sql .=
", weight_units = ".($this->weight_units !=
'' ?
"'".$this->db->escape($this->weight_units).
"'" :
'null');
1553 $sql .=
", length = ".($this->length !=
'' ?
"'".$this->db->escape($this->length).
"'" :
'null');
1554 $sql .=
", length_units = ".($this->length_units !=
'' ?
"'".$this->db->escape($this->length_units).
"'" :
'null');
1555 $sql .=
", width= ".($this->width !=
'' ?
"'".$this->db->escape($this->width).
"'" :
'null');
1556 $sql .=
", width_units = ".($this->width_units !=
'' ?
"'".$this->db->escape($this->width_units).
"'" :
'null');
1557 $sql .=
", height = ".($this->height !=
'' ?
"'".$this->db->escape($this->height).
"'" :
'null');
1558 $sql .=
", height_units = ".($this->height_units !=
'' ?
"'".$this->db->escape($this->height_units).
"'" :
'null');
1559 $sql .=
", surface = ".($this->surface !=
'' ?
"'".$this->db->escape($this->surface).
"'" :
'null');
1560 $sql .=
", surface_units = ".($this->surface_units !=
'' ?
"'".$this->db->escape($this->surface_units).
"'" :
'null');
1561 $sql .=
", volume = ".($this->volume !=
'' ?
"'".$this->db->escape($this->volume).
"'" :
'null');
1562 $sql .=
", volume_units = ".($this->volume_units !=
'' ?
"'".$this->db->escape($this->volume_units).
"'" :
'null');
1563 $sql .=
", fk_default_warehouse = ".($this->fk_default_warehouse > 0 ? ((int) $this->fk_default_warehouse) :
'null');
1564 $sql .=
", fk_default_workstation = ".($this->fk_default_workstation > 0 ? ((int) $this->fk_default_workstation) :
'null');
1565 $sql .=
", seuil_stock_alerte = ".((isset($this->seuil_stock_alerte) && is_numeric($this->seuil_stock_alerte)) ? (
float) $this->seuil_stock_alerte :
'null');
1566 $sql .=
", description = '".$this->db->escape($this->
description).
"'";
1567 $sql .=
", url = ".($this->url ?
"'".$this->db->escape($this->url).
"'" :
'null');
1568 $sql .=
", customcode = '".$this->db->escape($this->customcode).
"'";
1569 $sql .=
", fk_country = ".($this->country_id > 0 ? (int) $this->country_id :
'null');
1570 $sql .=
", fk_state = ".($this->state_id > 0 ? (int) $this->state_id :
'null');
1571 $sql .=
", lifetime = ".($this->lifetime > 0 ? (int) $this->lifetime :
'null');
1572 $sql .=
", qc_frequency = ".($this->qc_frequency > 0 ? (int) $this->qc_frequency :
'null');
1573 $sql .=
", note = ".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
'null');
1574 $sql .=
", note_public = ".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
'null');
1575 $sql .=
", duration = '".$this->db->escape($this->duration_value.$this->duration_unit).
"'";
1577 $sql .=
", accountancy_code_buy = '" . $this->db->escape($this->accountancy_code_buy) .
"'";
1578 $sql .=
", accountancy_code_buy_intra = '" . $this->db->escape($this->accountancy_code_buy_intra) .
"'";
1579 $sql .=
", accountancy_code_buy_export = '" . $this->db->escape($this->accountancy_code_buy_export) .
"'";
1580 $sql .=
", accountancy_code_sell= '" . $this->db->escape($this->accountancy_code_sell) .
"'";
1581 $sql .=
", accountancy_code_sell_intra= '" . $this->db->escape($this->accountancy_code_sell_intra) .
"'";
1582 $sql .=
", accountancy_code_sell_export= '" . $this->db->escape($this->accountancy_code_sell_export) .
"'";
1584 $sql .=
", desiredstock = ".((isset($this->desiredstock) && is_numeric($this->desiredstock)) ? (
float) $this->desiredstock :
"null");
1585 $sql .=
", cost_price = ".($this->cost_price !=
'' ? $this->db->escape($this->cost_price) :
'null');
1586 $sql .=
", fk_unit= ".(!$this->fk_unit ?
'NULL' : (int) $this->fk_unit);
1587 $sql .=
", price_autogen = ".(!$this->price_autogen ? 0 : 1);
1588 $sql .=
", fk_price_expression = ".($this->fk_price_expression != 0 ? (int) $this->fk_price_expression :
'NULL');
1589 $sql .=
", fk_user_modif = ".($user->id > 0 ? $user->id :
'NULL');
1590 $sql .=
", mandatory_period = ".($this->mandatory_period);
1592 $sql .=
" WHERE rowid = ".((int) $id);
1594 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
1596 $resql = $this->db->query($sql);
1603 $this->db->rollback();
1612 $this->db->query(
"DELETE FROM " . $this->db->prefix() .
"product_perentity WHERE fk_product = " . ((
int) $this->id) .
" AND entity = " . ((
int)
$conf->entity));
1614 $sql =
"INSERT INTO " . $this->db->prefix() .
"product_perentity (";
1615 $sql .=
" fk_product";
1617 $sql .=
", accountancy_code_buy";
1618 $sql .=
", accountancy_code_buy_intra";
1619 $sql .=
", accountancy_code_buy_export";
1620 $sql .=
", accountancy_code_sell";
1621 $sql .=
", accountancy_code_sell_intra";
1622 $sql .=
", accountancy_code_sell_export";
1623 $sql .=
") VALUES (";
1624 $sql .= ((int) $this->
id);
1625 $sql .=
", " . ((int)
$conf->entity);
1626 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy) .
"'";
1627 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_intra) .
"'";
1628 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_export) .
"'";
1629 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell) .
"'";
1630 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_intra) .
"'";
1631 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_export) .
"'";
1633 $result = $this->db->query($sql);
1636 $this->error =
'ErrorFailedToUpdateAccountancyForEntity';
1640 if (!$this->
hasbatch() && $this->oldcopy->hasbatch()) {
1642 $sql =
'SELECT pb.qty, ps.fk_entrepot, pb.batch FROM '.MAIN_DB_PREFIX.
'product_batch as pb';
1643 $sql .=
' INNER JOIN '.MAIN_DB_PREFIX.
'product_stock as ps ON (ps.rowid = pb.fk_product_stock)';
1644 $sql .=
' WHERE ps.fk_product = '.(int) $this->
id;
1646 $resql = $this->db->query($sql);
1650 while ($obj = $this->db->fetch_object($resql)) {
1652 $fk_entrepot = $obj->fk_entrepot;
1656 $batch = $obj->batch;
1659 $addOremove = $value > 0 ? 1 : 0;
1660 $label = $langs->trans(
'BatchStockMouvementAddInGlobal');
1661 $res = $this->
correct_stock_batch($user, $fk_entrepot, abs($value), $addOremove, $label, $price, $dlc, $dluo, $batch, $inventorycode,
'',
null, 0,
null,
true);
1664 $label = $langs->trans(
'BatchStockMouvementAddInGlobal');
1665 $res = $this->
correct_stock($user, $fk_entrepot, abs($value), (
int) empty($addOremove), $label, $price, $inventorycode,
'',
null, 0);
1684 if (!$error && !$notrigger) {
1686 $result = $this->
call_trigger(
'PRODUCT_MODIFY', $user);
1693 if (!$error && (is_object($this->oldcopy) && $this->oldcopy->ref !== $this->ref)) {
1695 if (
$conf->product->dir_output) {
1698 if (file_exists($olddir)) {
1702 $res = @rename($olddir, $newdir);
1704 $langs->load(
"errors");
1705 $this->error = $langs->trans(
'ErrorFailToRenameDir', $olddir, $newdir);
1709 require_once DOL_DOCUMENT_ROOT .
'/ecm/class/ecmfiles.class.php';
1710 $ecmfiles =
new EcmFiles($this->db);
1711 $ecmfiles->updateAfterRename(
"produit/".
dol_sanitizeFileName($this->oldcopy->ref),
"produit/".dol_sanitizeFileName($this->ref));
1718 if (isModEnabled(
'variants')) {
1719 include_once DOL_DOCUMENT_ROOT.
'/variants/class/ProductCombination.class.php';
1723 foreach ($comb->fetchAllByFkProductParent($this->id) as $currcomb) {
1724 $currcomb->updateProperties($this, $user);
1728 $this->db->commit();
1731 $this->db->rollback();
1735 if ($this->db->errno() ==
'DB_ERROR_RECORD_ALREADY_EXISTS') {
1736 $langs->load(
"errors");
1737 if (empty(
$conf->barcode->enabled) || empty($this->barcode)) {
1738 $this->error = $langs->trans(
"Error").
" : ".$langs->trans(
"ErrorProductAlreadyExists", $this->
ref);
1740 $this->error = $langs->trans(
"Error").
" : ".$langs->trans(
"ErrorProductBarCodeAlreadyExists", $this->barcode);
1742 $this->errors[] = $this->error;
1743 $this->db->rollback();
1746 $this->error = $langs->trans(
"Error").
" : ".$this->db->error().
" - ".$sql;
1747 $this->errors[] = $this->error;
1748 $this->db->rollback();
1753 $this->db->rollback();
1754 dol_syslog(get_class($this).
"::Update fails verify ".implode(
',', $this->errors), LOG_WARNING);
1766 public function delete(
User $user, $notrigger = 0)
1769 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1774 if (empty($this->
id)) {
1775 $this->error =
"Object must be fetched before calling delete";
1778 if (($this->
isProduct() && !$user->
hasRight(
'produit',
'supprimer')) || ($this->isService() && !$user->hasRight(
'service',
'supprimer'))) {
1779 $this->error =
"ErrorForbidden";
1784 if (empty($objectisused)) {
1787 if (!$error && empty($notrigger)) {
1789 $result = $this->
call_trigger(
'PRODUCT_DELETE', $user);
1798 $sql =
"DELETE FROM ".$this->db->prefix().
'product_batch';
1799 $sql .=
" WHERE fk_product_stock IN (";
1800 $sql .=
"SELECT rowid FROM ".$this->db->prefix().
'product_stock';
1801 $sql .=
" WHERE fk_product = ".((int) $this->
id).
")";
1803 $result = $this->db->query($sql);
1806 $this->errors[] = $this->db->lasterror();
1812 $elements = array(
'product_fournisseur_price',
'product_price',
'product_lang',
'categorie_product',
'product_stock',
'product_customer_price',
'product_lot');
1813 foreach ($elements as $table) {
1815 $sql =
"DELETE FROM ".$this->db->prefix().$table;
1816 $sql .=
" WHERE fk_product = ".(int) $this->
id;
1818 $result = $this->db->query($sql);
1821 $this->errors[] = $this->db->lasterror();
1828 include_once DOL_DOCUMENT_ROOT.
'/variants/class/ProductCombination.class.php';
1829 include_once DOL_DOCUMENT_ROOT.
'/variants/class/ProductCombination2ValuePair.class.php';
1834 if ($prodcomb->deleteByFkProductParent($user, $this->id) < 0) {
1836 $this->errors[] =
'Error deleting combinations';
1840 if (!$error && ($prodcomb->fetchByFkProductChild($this->id) > 0) && ($prodcomb->delete($user) < 0)) {
1842 $this->errors[] =
'Error deleting child combination';
1848 $sql =
"DELETE FROM ".$this->db->prefix().
"product_association";
1849 $sql .=
" WHERE fk_product_pere = ".(int) $this->
id.
" OR fk_product_fils = ".(
int) $this->id;
1851 $result = $this->db->query($sql);
1854 $this->errors[] = $this->db->lasterror();
1863 dol_syslog(get_class($this).
"::delete error -4 ".$this->error, LOG_ERR);
1869 $sqlz =
"DELETE FROM ".$this->db->prefix().
"product";
1870 $sqlz .=
" WHERE rowid = ".(int) $this->
id;
1872 $resultz = $this->db->query($sqlz);
1875 $this->errors[] = $this->db->lasterror();
1891 if ($conf->product->dir_output) {
1892 $dir =
$conf->product->dir_output.
"/".$ref;
1893 if (file_exists($dir)) {
1896 $this->errors[] =
'ErrorFailToDeleteDir';
1904 $this->db->commit();
1907 foreach ($this->errors as $errmsg) {
1908 dol_syslog(get_class($this).
"::delete ".$errmsg, LOG_ERR);
1909 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1911 $this->db->rollback();
1915 $this->error =
"ErrorRecordIsUsedCantDelete";
1929 $sellByLabel = $langs->trans(
'SellByDate');
1930 $eatByLabel = $langs->trans(
'EatByDate');
1932 self::SELL_OR_EAT_BY_MANDATORY_ID_NONE => $langs->trans(
'BatchSellOrEatByMandatoryNone'),
1933 self::SELL_OR_EAT_BY_MANDATORY_ID_SELL_BY => $sellByLabel,
1934 self::SELL_OR_EAT_BY_MANDATORY_ID_EAT_BY => $eatByLabel,
1935 self::SELL_OR_EAT_BY_MANDATORY_ID_SELL_AND_EAT => $langs->trans(
'BatchSellOrEatByMandatoryAll', $sellByLabel, $eatByLabel),
1946 $sellOrEatByMandatoryLabel =
'';
1949 if (isset($sellOrEatByMandatoryList[$this->sell_or_eat_by_mandatory])) {
1950 $sellOrEatByMandatoryLabel = $sellOrEatByMandatoryList[$this->sell_or_eat_by_mandatory];
1953 return $sellOrEatByMandatoryLabel;
1966 $langs_available = $langs->get_available_languages(DOL_DOCUMENT_ROOT, 0, 2);
1967 $current_lang = $langs->getDefaultLang();
1969 foreach ($langs_available as $key => $value) {
1970 if ($key == $current_lang) {
1971 $sql =
"SELECT rowid";
1972 $sql .=
" FROM ".$this->db->prefix().
"product_lang";
1973 $sql .=
" WHERE fk_product = ".((int) $this->
id);
1974 $sql .=
" AND lang = '".$this->db->escape($key).
"'";
1976 $result = $this->db->query($sql);
1978 if ($this->db->num_rows($result)) {
1979 $sql2 =
"UPDATE ".$this->db->prefix().
"product_lang";
1981 $sql2 .=
" label='".$this->db->escape($this->label).
"',";
1982 $sql2 .=
" description='".$this->db->escape($this->
description).
"'";
1984 $sql2 .=
", note='".$this->db->escape($this->other).
"'";
1986 $sql2 .=
" WHERE fk_product = ".((int) $this->
id).
" AND lang = '".$this->db->escape($key).
"'";
1988 $sql2 =
"INSERT INTO ".$this->db->prefix().
"product_lang (fk_product, lang, label, description";
1993 $sql2 .=
" VALUES(".((int) $this->
id).
",'".$this->db->escape($key).
"','".$this->db->escape($this->label).
"',";
1994 $sql2 .=
" '".$this->db->escape($this->
description).
"'";
1996 $sql2 .=
", '".$this->db->escape($this->other).
"'";
2000 dol_syslog(get_class($this).
'::setMultiLangs key = current_lang = '.$key);
2001 if (!$this->db->query($sql2)) {
2002 $this->error = $this->db->lasterror();
2005 } elseif (isset($this->multilangs[$key])) {
2006 if (empty($this->multilangs[$key][
"label"])) {
2007 $this->errors[] = $key .
' : ' . $langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv(
"Label"));
2011 $sql =
"SELECT rowid";
2012 $sql .=
" FROM ".$this->db->prefix().
"product_lang";
2013 $sql .=
" WHERE fk_product = ".((int) $this->
id);
2014 $sql .=
" AND lang = '".$this->db->escape($key).
"'";
2016 $result = $this->db->query($sql);
2018 if ($this->db->num_rows($result)) {
2019 $sql2 =
"UPDATE ".$this->db->prefix().
"product_lang";
2021 $sql2 .=
" label = '".$this->db->escape($this->multilangs[
"$key"][
"label"]).
"',";
2022 $sql2 .=
" description = '".$this->db->escape($this->multilangs[
"$key"][
"description"]).
"'";
2025 $sql2 .=
", note = '".$this->db->escape($this->multilangs[
"$key"][
"other"]).
"'";
2027 $sql2 .=
" WHERE fk_product = ".((int) $this->
id).
" AND lang = '".$this->db->escape($key).
"'";
2029 $sql2 =
"INSERT INTO ".$this->db->prefix().
"product_lang (fk_product, lang, label, description";
2034 $sql2 .=
" VALUES(".((int) $this->
id).
",'".$this->db->escape($key).
"','".$this->db->escape($this->multilangs[
"$key"][
"label"]).
"',";
2035 $sql2 .=
" '".$this->db->escape($this->multilangs[
"$key"][
"description"]).
"'";
2038 $sql2 .=
", '".$this->db->escape($this->multilangs[
"$key"][
"other"]).
"'";
2044 if ($this->multilangs[
"$key"][
"label"] || $this->multilangs[
"$key"][
"description"]) {
2045 if (!$this->db->query($sql2)) {
2046 $this->error = $this->db->lasterror();
2056 $result = $this->
call_trigger(
'PRODUCT_SET_MULTILANGS', $user);
2058 $this->error = $this->db->lasterror();
2076 $sql =
"DELETE FROM ".$this->db->prefix().
"product_lang";
2077 $sql .=
" WHERE fk_product = ".((int) $this->
id).
" AND lang = '".$this->db->escape($langtodelete).
"'";
2079 dol_syslog(get_class($this).
'::delMultiLangs', LOG_DEBUG);
2080 $result = $this->db->query($sql);
2083 $result = $this->
call_trigger(
'PRODUCT_DEL_MULTILANGS', $user);
2085 $this->error = $this->db->lasterror();
2086 dol_syslog(get_class($this).
'::delMultiLangs error='.$this->error, LOG_ERR);
2092 $this->error = $this->db->lasterror();
2093 dol_syslog(get_class($this).
'::delMultiLangs error='.$this->error, LOG_ERR);
2114 if ($type ==
'buy') {
2115 $field =
'accountancy_code_buy';
2116 } elseif ($type ==
'buy_intra') {
2117 $field =
'accountancy_code_buy_intra';
2118 } elseif ($type ==
'buy_export') {
2119 $field =
'accountancy_code_buy_export';
2120 } elseif ($type ==
'sell') {
2121 $field =
'accountancy_code_sell';
2122 } elseif ($type ==
'sell_intra') {
2123 $field =
'accountancy_code_sell_intra';
2124 } elseif ($type ==
'sell_export') {
2125 $field =
'accountancy_code_sell_export';
2130 $sql =
"UPDATE ".$this->db->prefix().$this->table_element.
" SET ";
2131 $sql .=
"$field = '".$this->db->escape($value).
"'";
2132 $sql .=
" WHERE rowid = ".((int) $this->
id);
2135 $resql = $this->db->query($sql);
2139 $result = $this->
call_trigger(
'PRODUCT_MODIFY', $user);
2146 $this->db->rollback();
2150 $this->$field = $value;
2152 $this->db->commit();
2155 $this->error = $this->db->lasterror();
2156 $this->db->rollback();
2170 $current_lang = $langs->getDefaultLang();
2172 $sql =
"SELECT lang, label, description, note as other";
2173 $sql .=
" FROM ".$this->db->prefix().
"product_lang";
2174 $sql .=
" WHERE fk_product = ".((int) $this->
id);
2176 $result = $this->db->query($sql);
2178 while ($obj = $this->db->fetch_object($result)) {
2180 if ($obj->lang == $current_lang) {
2181 $this->label = $obj->label;
2183 $this->other = $obj->other;
2185 $this->multilangs[(string) $obj->lang][
"label"] = $obj->label;
2186 $this->multilangs[(string) $obj->lang][
"description"] = $obj->description;
2187 $this->multilangs[(string) $obj->lang][
"other"] = $obj->other;
2191 $this->error =
"Error: ".$this->db->lasterror().
" - ".$sql;
2204 $testExit = array(
'multiprices',
'multiprices_ttc',
'multiprices_base_type',
'multiprices_min',
'multiprices_min_ttc',
'multiprices_tva_tx',
'multiprices_recuperableonly');
2206 foreach ($testExit as $field) {
2207 if (!isset($this->$field)) {
2210 $tmparray = $this->$field;
2211 if (!isset($tmparray[$level])) {
2217 'level' => $level ? $level : 1,
2218 'multiprices' => (float) $this->multiprices[$level],
2219 'multiprices_ttc' => (
float) $this->multiprices_ttc[$level],
2220 'multiprices_base_type' => $this->multiprices_base_type[$level],
2221 'multiprices_min' => (float) $this->multiprices_min[$level],
2222 'multiprices_min_ttc' => (
float) $this->multiprices_min_ttc[$level],
2223 'multiprices_tva_tx' => (float) $this->multiprices_tva_tx[$level],
2224 'multiprices_recuperableonly' => (
float) $this->multiprices_recuperableonly[$level],
2247 if (empty($this->price_by_qty)) {
2248 $this->price_by_qty = 0;
2252 $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,";
2253 $sql .=
" localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, price_min,price_min_ttc,price_by_qty,entity,fk_price_expression) ";
2254 $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).
",";
2255 $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');
2258 dol_syslog(get_class($this).
"::_log_price", LOG_DEBUG);
2259 $resql = $this->db->query($sql);
2261 $this->error = $this->db->lasterror();
2281 $sql =
"DELETE FROM ".$this->db->prefix().
"product_price_by_qty";
2282 $sql .=
" WHERE fk_product_price = ".((int) $rowid);
2283 $resql = $this->db->query($sql);
2285 $sql =
"DELETE FROM ".$this->db->prefix().
"product_price";
2286 $sql .=
" WHERE rowid=".((int) $rowid);
2287 $resql = $this->db->query($sql);
2291 $this->error = $this->db->lasterror();
2306 public function getSellPrice($thirdparty_seller, $thirdparty_buyer, $pqp = 0)
2308 global $hookmanager, $action;
2311 if (is_object($hookmanager)) {
2312 $parameters = array(
'thirdparty_seller' => $thirdparty_seller,
'thirdparty_buyer' => $thirdparty_buyer,
'pqp' => $pqp);
2314 $reshook = $hookmanager->executeHooks(
'getSellPrice', $parameters, $this, $action);
2316 return $hookmanager->resArray;
2321 $tva_tx =
get_default_tva($thirdparty_seller, $thirdparty_buyer, $this->
id);
2322 $tva_npr =
get_default_npr($thirdparty_seller, $thirdparty_buyer, $this->
id);
2323 if (empty($tva_tx)) {
2327 $pu_ht = $this->price;
2328 $pu_ttc = $this->price_ttc;
2329 $price_min = $this->price_min;
2330 $price_base_type = $this->price_base_type;
2334 require_once DOL_DOCUMENT_ROOT.
'/product/class/productcustomerprice.class.php';
2338 $filter = array(
't.fk_product' => $this->
id,
't.fk_soc' => $thirdparty_buyer->id);
2341 $pricebycustomerexist =
false;
2342 $result = $prodcustprice->fetchAll(
'',
'', 0, 0, $filter);
2344 if (count($prodcustprice->lines) > 0) {
2345 $pricebycustomerexist =
true;
2346 $pu_ht =
price($prodcustprice->lines[0]->price);
2347 $price_min =
price($prodcustprice->lines[0]->price_min);
2348 $pu_ttc =
price($prodcustprice->lines[0]->price_ttc);
2349 $price_base_type = $prodcustprice->lines[0]->price_base_type;
2350 $tva_tx = $prodcustprice->lines[0]->tva_tx;
2351 if ($prodcustprice->lines[0]->default_vat_code && !preg_match(
'/\(.*\)/', $tva_tx)) {
2352 $tva_tx .=
' ('.$prodcustprice->lines[0]->default_vat_code.
')';
2354 $tva_npr = $prodcustprice->lines[0]->recuperableonly;
2355 if (empty($tva_tx)) {
2361 if (!$pricebycustomerexist && !empty($thirdparty_buyer->price_level)) {
2362 $pu_ht = $this->multiprices[$thirdparty_buyer->price_level];
2363 $pu_ttc = $this->multiprices_ttc[$thirdparty_buyer->price_level];
2364 $price_min = $this->multiprices_min[$thirdparty_buyer->price_level];
2365 $price_base_type = $this->multiprices_base_type[$thirdparty_buyer->price_level];
2368 if (isset($this->multiprices_tva_tx[$thirdparty_buyer->price_level])) {
2369 $tva_tx = $this->multiprices_tva_tx[$thirdparty_buyer->price_level];
2371 if (isset($this->multiprices_recuperableonly[$thirdparty_buyer->price_level])) {
2372 $tva_npr = $this->multiprices_recuperableonly[$thirdparty_buyer->price_level];
2374 if (empty($tva_tx)) {
2379 } elseif (
getDolGlobalString(
'PRODUIT_MULTIPRICES') && !empty($thirdparty_buyer->price_level)) {
2380 $pu_ht = $this->multiprices[$thirdparty_buyer->price_level];
2381 $pu_ttc = $this->multiprices_ttc[$thirdparty_buyer->price_level];
2382 $price_min = $this->multiprices_min[$thirdparty_buyer->price_level];
2383 $price_base_type = $this->multiprices_base_type[$thirdparty_buyer->price_level];
2385 if (isset($this->multiprices_tva_tx[$thirdparty_buyer->price_level])) {
2386 $tva_tx = $this->multiprices_tva_tx[$thirdparty_buyer->price_level];
2388 if (isset($this->multiprices_recuperableonly[$thirdparty_buyer->price_level])) {
2389 $tva_npr = $this->multiprices_recuperableonly[$thirdparty_buyer->price_level];
2391 if (empty($tva_tx)) {
2397 require_once DOL_DOCUMENT_ROOT.
'/product/class/productcustomerprice.class.php';
2401 $filter = array(
't.fk_product' => $this->
id,
't.fk_soc' => $thirdparty_buyer->id);
2403 $result = $prodcustprice->fetchAll(
'',
'', 0, 0, $filter);
2405 if (count($prodcustprice->lines) > 0) {
2406 $pu_ht =
price($prodcustprice->lines[0]->price);
2407 $price_min =
price($prodcustprice->lines[0]->price_min);
2408 $pu_ttc =
price($prodcustprice->lines[0]->price_ttc);
2409 $price_base_type = $prodcustprice->lines[0]->price_base_type;
2410 $tva_tx = $prodcustprice->lines[0]->tva_tx;
2411 if ($prodcustprice->lines[0]->default_vat_code && !preg_match(
'/\(.*\)/', $tva_tx)) {
2412 $tva_tx .=
' ('.$prodcustprice->lines[0]->default_vat_code.
')';
2414 $tva_npr = $prodcustprice->lines[0]->recuperableonly;
2415 if (empty($tva_tx)) {
2422 if ($this->prices_by_qty[0]) {
2425 foreach ($this->prices_by_qty_list[0] as $priceforthequantityarray) {
2426 if ($priceforthequantityarray[
'rowid'] != $pqp) {
2430 if ($priceforthequantityarray[
'price_base_type'] ==
'HT') {
2431 $pu_ht = $priceforthequantityarray[
'unitprice'];
2433 $pu_ttc = $priceforthequantityarray[
'unitprice'];
2440 if ($this->prices_by_qty[$thirdparty_buyer->price_level]) {
2443 foreach ($this->prices_by_qty_list[$thirdparty_buyer->price_level] as $priceforthequantityarray) {
2444 if ($priceforthequantityarray[
'rowid'] != $pqp) {
2448 if ($priceforthequantityarray[
'price_base_type'] ==
'HT') {
2449 $pu_ht = $priceforthequantityarray[
'unitprice'];
2451 $pu_ttc = $priceforthequantityarray[
'unitprice'];
2458 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);
2475 public function get_buyprice($prodfournprice, $qty, $product_id = 0, $fourn_ref =
'', $fk_soc = 0)
2478 global $action, $hookmanager;
2481 if (is_object($hookmanager)) {
2482 $parameters = array(
2483 'prodfournprice' => $prodfournprice,
2485 'product_id' => $product_id,
2486 'fourn_ref' => $fourn_ref,
2487 'fk_soc' => $fk_soc,
2490 $reshook = $hookmanager->executeHooks(
'getBuyPrice', $parameters, $this, $action);
2492 return $hookmanager->resArray;
2499 $sql =
"SELECT pfp.rowid, pfp.price as price, pfp.quantity as quantity, pfp.remise_percent, pfp.fk_soc,";
2500 $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,";
2501 $sql .=
" pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code,";
2502 $sql .=
" pfp.packaging";
2503 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price as pfp";
2504 $sql .=
" WHERE pfp.rowid = ".((int) $prodfournprice);
2506 $sql .=
" AND pfp.quantity <= ".((float) $qty);
2508 $sql .=
" ORDER BY pfp.quantity DESC";
2510 dol_syslog(get_class($this).
"::get_buyprice first search by prodfournprice/qty", LOG_DEBUG);
2511 $resql = $this->db->query($sql);
2513 $obj = $this->db->fetch_object($resql);
2514 if ($obj && $obj->quantity > 0) {
2515 if (isModEnabled(
'dynamicprices') && !empty($obj->fk_supplier_price_expression)) {
2517 $prod_supplier->product_fourn_price_id = $obj->rowid;
2518 $prod_supplier->id = $obj->fk_product;
2519 $prod_supplier->fourn_qty = $obj->quantity;
2520 $prod_supplier->fourn_tva_tx = $obj->tva_tx;
2521 $prod_supplier->fk_supplier_price_expression = $obj->fk_supplier_price_expression;
2523 include_once DOL_DOCUMENT_ROOT.
'/product/dynamic_price/class/price_parser.class.php';
2525 $price_result = $priceparser->parseProductSupplier($prod_supplier);
2526 if ($price_result >= 0) {
2527 $obj->price = $price_result;
2530 $this->product_fourn_price_id = $obj->rowid;
2531 $this->buyprice = $obj->price;
2532 $this->fourn_pu = $obj->price / $obj->quantity;
2533 $this->fourn_price_base_type =
'HT';
2534 $this->fourn_socid = $obj->fk_soc;
2535 $this->ref_fourn = $obj->ref_supplier;
2536 $this->ref_supplier = $obj->ref_supplier;
2537 $this->desc_supplier = $obj->desc_supplier;
2538 $this->remise_percent = $obj->remise_percent;
2539 $this->vatrate_supplier = $obj->tva_tx;
2540 $this->default_vat_code_supplier = $obj->default_vat_code;
2541 $this->fourn_multicurrency_price = $obj->multicurrency_price;
2542 $this->fourn_multicurrency_unitprice = $obj->multicurrency_unitprice;
2543 $this->fourn_multicurrency_tx = $obj->multicurrency_tx;
2544 $this->fourn_multicurrency_id = $obj->fk_multicurrency;
2545 $this->fourn_multicurrency_code = $obj->multicurrency_code;
2547 $this->packaging = $obj->packaging;
2549 $result = $obj->fk_product;
2553 $sql =
"SELECT pfp.rowid, pfp.price as price, pfp.quantity as quantity, pfp.remise_percent, pfp.fk_soc,";
2554 $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,";
2555 $sql .=
" pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code,";
2556 $sql .=
" pfp.packaging";
2557 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price as pfp";
2558 $sql .=
" WHERE 1 = 1";
2559 if ($product_id > 0) {
2560 $sql .=
" AND pfp.fk_product = ".((int) $product_id);
2562 if ($fourn_ref !=
'none') {
2563 $sql .=
" AND pfp.ref_fourn = '".$this->db->escape($fourn_ref).
"'";
2566 $sql .=
" AND pfp.fk_soc = ".((int) $fk_soc);
2569 $sql .=
" AND pfp.quantity <= ".((float) $qty);
2571 $sql .=
" ORDER BY pfp.quantity DESC";
2574 dol_syslog(get_class($this).
"::get_buyprice second search from qty/ref/product_id", LOG_DEBUG);
2575 $resql = $this->db->query($sql);
2577 $obj = $this->db->fetch_object($resql);
2578 if ($obj && $obj->quantity > 0) {
2579 if (isModEnabled(
'dynamicprices') && !empty($obj->fk_supplier_price_expression)) {
2581 $prod_supplier->product_fourn_price_id = $obj->rowid;
2582 $prod_supplier->id = $obj->fk_product;
2583 $prod_supplier->fourn_qty = $obj->quantity;
2584 $prod_supplier->fourn_tva_tx = $obj->tva_tx;
2585 $prod_supplier->fk_supplier_price_expression = $obj->fk_supplier_price_expression;
2587 include_once DOL_DOCUMENT_ROOT.
'/product/dynamic_price/class/price_parser.class.php';
2589 $price_result = $priceparser->parseProductSupplier($prod_supplier);
2591 $obj->price = $price_result;
2594 $this->product_fourn_price_id = $obj->rowid;
2595 $this->buyprice = $obj->price;
2596 $this->fourn_qty = $obj->quantity;
2597 $this->fourn_pu = $obj->price / $obj->quantity;
2598 $this->fourn_price_base_type =
'HT';
2599 $this->fourn_socid = $obj->fk_soc;
2600 $this->ref_fourn = $obj->ref_supplier;
2601 $this->ref_supplier = $obj->ref_supplier;
2602 $this->desc_supplier = $obj->desc_supplier;
2603 $this->remise_percent = $obj->remise_percent;
2604 $this->vatrate_supplier = $obj->tva_tx;
2605 $this->default_vat_code_supplier = $obj->default_vat_code;
2606 $this->fourn_multicurrency_price = $obj->multicurrency_price;
2607 $this->fourn_multicurrency_unitprice = $obj->multicurrency_unitprice;
2608 $this->fourn_multicurrency_tx = $obj->multicurrency_tx;
2609 $this->fourn_multicurrency_id = $obj->fk_multicurrency;
2610 $this->fourn_multicurrency_code = $obj->multicurrency_code;
2612 $this->packaging = $obj->packaging;
2614 $result = $obj->fk_product;
2620 $this->error = $this->db->lasterror();
2625 $this->error = $this->db->lasterror();
2649 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)
2655 dol_syslog(get_class($this).
"::update_price id=".$id.
" newprice=".$newprice.
" newpricebase=".$newpricebase.
" newminprice=".$newminprice.
" level=".$level.
" npr=".$newnpr.
" newdefaultvatcode=".$newdefaultvatcode);
2658 if (empty($this->tva_tx)) {
2659 $this->tva_tx = 0.0;
2661 if (empty($newnpr)) {
2664 if (empty($newminprice)) {
2669 if ($newvat ===
null || $newvat ==
'') {
2670 $newvat = (float) $this->tva_tx;
2673 $localtaxtype1 =
'';
2674 $localtaxtype2 =
'';
2679 return $this->
generateMultiprices($user, $newprice, $newpricebase, $newvat, $newnpr, $newpbq);
2682 if (!empty($newminprice) && ($newminprice > $newprice)) {
2683 $this->error =
'ErrorPriceCantBeLowerThanMinPrice';
2687 if ($newprice === 0 || $newprice !==
'') {
2688 if ($newpricebase ==
'TTC') {
2689 $price_ttc = (float)
price2num($newprice,
'MU');
2690 $price = (float)
price2num($newprice) / (1 + ((float) $newvat / 100));
2691 $price = (float)
price2num($price,
'MU');
2693 if ((
string) $newminprice !=
'0') {
2694 $price_min_ttc = (float)
price2num($newminprice,
'MU');
2695 $price_min = (float)
price2num($newminprice) / (1 + ($newvat / 100));
2696 $price_min = (float)
price2num($price_min,
'MU');
2699 $price_min_ttc = 0.0;
2702 $price = (float)
price2num($newprice,
'MU');
2703 $price_ttc = ($newnpr != 1) ? (
float)
price2num($newprice) * (1 + ($newvat / 100)) : $price;
2704 $price_ttc = (float)
price2num($price_ttc,
'MU');
2706 if ((
string) $newminprice !=
'0') {
2707 $price_min = (float)
price2num($newminprice,
'MU');
2708 $price_min_ttc = (float)
price2num($newminprice) * (1 + ($newvat / 100));
2709 $price_min_ttc = (float)
price2num($price_min_ttc,
'MU');
2713 $price_min_ttc = 0.0;
2717 if (count($localtaxes_array) > 0) {
2718 $localtaxtype1 = $localtaxes_array[
'0'];
2719 $localtax1 = $localtaxes_array[
'1'];
2720 $localtaxtype2 = $localtaxes_array[
'2'];
2721 $localtax2 = $localtaxes_array[
'3'];
2724 if (!empty($newdefaultvatcode)) {
2727 $sql =
"SELECT t.rowid, t.code, t.recuperableonly as tva_npr, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
2728 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_tva as t, ".MAIN_DB_PREFIX.
"c_country as c";
2729 $sql .=
" WHERE t.fk_pays = c.rowid AND c.code = '".$this->db->escape($mysoc->country_code).
"'";
2730 $sql .=
" AND t.taux = ".((float) $newdefaultvatcode).
" AND t.active = 1";
2731 $sql .=
" AND t.code = '".$this->db->escape($newdefaultvatcode).
"'";
2732 $resql = $this->db->query($sql);
2734 $obj = $this->db->fetch_object($resql);
2736 $npr = $obj->tva_npr;
2737 $localtax1 = $obj->localtax1;
2738 $localtax2 = $obj->localtax2;
2739 $localtaxtype1 = $obj->localtax1_type;
2740 $localtaxtype2 = $obj->localtax2_type;
2745 $localtaxtype1 =
'0';
2747 $localtaxtype2 =
'0';
2751 if (empty($localtax1)) {
2754 if (empty($localtax2)) {
2762 $sql =
"UPDATE ".$this->db->prefix().
"product SET";
2763 $sql .=
" price_base_type = '".$this->db->escape($newpricebase).
"',";
2764 $sql .=
" price = ".(float) $price.
",";
2765 $sql .=
" price_ttc = ".(float) $price_ttc.
",";
2766 $sql .=
" price_min = ".(float) $price_min.
",";
2767 $sql .=
" price_min_ttc = ".(float) $price_min_ttc.
",";
2768 $sql .=
" localtax1_tx = ".($localtax1 >= 0 ? (float) $localtax1 :
'NULL').
",";
2769 $sql .=
" localtax2_tx = ".($localtax2 >= 0 ? (float) $localtax2 :
'NULL').
",";
2770 $sql .=
" localtax1_type = ".($localtaxtype1 !=
'' ?
"'".$this->db->escape($localtaxtype1).
"'" :
"'0'").
",";
2771 $sql .=
" localtax2_type = ".($localtaxtype2 !=
'' ?
"'".$this->db->escape($localtaxtype2).
"'" :
"'0'").
",";
2772 $sql .=
" default_vat_code = ".($newdefaultvatcode ?
"'".$this->db->escape($newdefaultvatcode).
"'" :
"null").
",";
2773 $sql .=
" price_label = ".(!empty($price_label) ?
"'".$this->db->escape($price_label).
"'" :
"null").
",";
2774 $sql .=
" tva_tx = ".(float)
price2num($newvat).
",";
2775 $sql .=
" recuperableonly = '".$this->db->escape($newnpr).
"'";
2776 $sql .=
" WHERE rowid = ".((int) $id);
2778 dol_syslog(get_class($this).
"::update_price", LOG_DEBUG);
2779 $resql = $this->db->query($sql);
2781 $this->multiprices[$level] = $price;
2782 $this->multiprices_ttc[$level] = $price_ttc;
2783 $this->multiprices_min[$level] = $price_min;
2784 $this->multiprices_min_ttc[$level] = $price_min_ttc;
2785 $this->multiprices_base_type[$level] = $newpricebase;
2786 $this->multiprices_default_vat_code[$level] = $newdefaultvatcode;
2787 $this->multiprices_tva_tx[$level] = $newvat;
2788 $this->multiprices_recuperableonly[$level] = $newnpr;
2790 $this->
price = $price;
2791 $this->price_label = $price_label;
2792 $this->price_ttc = $price_ttc;
2793 $this->price_min = $price_min;
2794 $this->price_min_ttc = $price_min_ttc;
2795 $this->price_base_type = $newpricebase;
2796 $this->default_vat_code = $newdefaultvatcode;
2797 $this->tva_tx = $newvat;
2798 $this->tva_npr = $newnpr;
2801 $this->localtax1_tx = $localtax1;
2802 $this->localtax2_tx = $localtax2;
2803 $this->localtax1_type = $localtaxtype1;
2804 $this->localtax2_type = $localtaxtype2;
2807 $this->price_by_qty = $newpbq;
2811 if (!empty(array_diff_assoc($newPriceData, $lastPriceData)) || !
getDolGlobalString(
'PRODUIT_MULTIPRICES')) {
2815 $this->level = $level;
2819 $result = $this->
call_trigger(
'PRODUCT_PRICE_MODIFY', $user);
2821 $this->db->rollback();
2827 $this->db->commit();
2829 $this->db->rollback();
2830 $this->error = $this->db->lasterror();
2849 $this->fk_price_expression = $expression_id;
2851 return $this->
update($this->
id, $user);
2866 public function fetch($id = 0, $ref =
'', $ref_ext =
'', $barcode =
'', $ignore_expression = 0, $ignore_price_load = 0, $ignore_lang_load = 0)
2868 include_once DOL_DOCUMENT_ROOT.
'/core/lib/company.lib.php';
2872 dol_syslog(get_class($this).
"::fetch id=".$id.
" ref=".$ref.
" ref_ext=".$ref_ext);
2875 if (!$id && !$ref && !$ref_ext && !$barcode) {
2876 $this->error =
'ErrorWrongParameters';
2877 dol_syslog(get_class($this).
"::fetch ".$this->error, LOG_ERR);
2881 $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,";
2882 $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,";
2883 $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,";
2884 $sql .=
" p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.last_main_doc,";
2885 $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,";
2887 $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,";
2889 $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,";
2894 $separatedEntityPMP =
false;
2895 $separatedStock =
false;
2896 $visibleWarehousesEntities =
$conf->entity;
2899 $checkPMPPerEntity = $this->db->query(
"SELECT pmp FROM " . $this->db->prefix() .
"product_perentity WHERE fk_product = ".((int) $id).
" AND entity = ".(
int)
$conf->entity);
2900 if ($this->db->num_rows($checkPMPPerEntity) > 0) {
2901 $separatedEntityPMP =
true;
2905 $separatedStock =
true;
2906 if (isset($mc->sharings[
'stock']) && !empty($mc->sharings[
'stock'])) {
2907 $visibleWarehousesEntities .=
"," . implode(
",", $mc->sharings[
'stock']);
2910 if ($separatedEntityPMP) {
2911 $sql .=
" ppe.pmp,";
2915 $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,";
2916 $sql .=
" p.fk_price_expression, p.price_autogen, p.model_pdf,";
2917 $sql .=
" p.price_label,";
2918 if ($separatedStock) {
2919 $sql .=
" SUM(sp.reel) as stock";
2923 $sql .=
" FROM ".$this->db->prefix().
"product as p";
2925 $sql .=
" LEFT JOIN " . $this->db->prefix() .
"product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int)
$conf->entity);
2927 if ($separatedStock) {
2928 $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).
"))";
2932 $sql .=
" WHERE p.rowid = ".((int) $id);
2934 $sql .=
" WHERE p.entity IN (".getEntity($this->element).
")";
2936 $sql .=
" AND p.ref = '".$this->db->escape($ref).
"'";
2937 } elseif ($ref_ext) {
2938 $sql .=
" AND p.ref_ext = '".$this->db->escape($ref_ext).
"'";
2939 } elseif ($barcode) {
2940 $sql .=
" AND p.barcode = '".$this->db->escape($barcode).
"'";
2943 if ($separatedStock) {
2944 $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,";
2945 $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,";
2946 $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,";
2947 $sql .=
" p.length, p.length_units, p.width, p.width_units, p.height, p.height_units,";
2948 $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,";
2950 $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,";
2952 $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,";
2954 if ($separatedEntityPMP) {
2955 $sql .=
" ppe.pmp,";
2959 $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,";
2960 $sql .=
" p.fk_price_expression, p.price_autogen, p.model_pdf";
2961 $sql .=
" ,p.price_label";
2962 if (!$separatedStock) {
2963 $sql .=
", p.stock";
2967 $resql = $this->db->query($sql);
2969 unset($this->oldcopy);
2971 if ($this->db->num_rows($resql) > 0) {
2972 $obj = $this->db->fetch_object($resql);
2974 $this->
id = $obj->rowid;
2975 $this->
ref = $obj->ref;
2976 $this->ref_ext = $obj->ref_ext;
2977 $this->label = $obj->label;
2979 $this->url = $obj->url;
2980 $this->note_public = $obj->note_public;
2981 $this->note_private = $obj->note_private;
2982 $this->note = $obj->note_private;
2984 $this->
type = $obj->fk_product_type;
2985 $this->price_label = $obj->price_label;
2986 $this->
status = $obj->tosell;
2987 $this->status_buy = $obj->tobuy;
2988 $this->status_batch = $obj->tobatch;
2989 $this->sell_or_eat_by_mandatory = $obj->sell_or_eat_by_mandatory;
2990 $this->batch_mask = $obj->batch_mask;
2992 $this->customcode = $obj->customcode;
2993 $this->country_id = $obj->fk_country;
2994 $this->country_code =
getCountry($this->country_id,
'2', $this->db);
2995 $this->state_id = $obj->fk_state;
2996 $this->lifetime = $obj->lifetime;
2997 $this->qc_frequency = $obj->qc_frequency;
2998 $this->
price = $obj->price;
2999 $this->price_ttc = $obj->price_ttc;
3000 $this->price_min = $obj->price_min;
3001 $this->price_min_ttc = $obj->price_min_ttc;
3002 $this->price_base_type = $obj->price_base_type;
3003 $this->cost_price = $obj->cost_price;
3004 $this->default_vat_code = $obj->default_vat_code;
3005 $this->tva_tx = $obj->tva_tx;
3007 $this->tva_npr = $obj->tva_npr;
3009 $this->localtax1_tx = $obj->localtax1_tx;
3010 $this->localtax2_tx = $obj->localtax2_tx;
3011 $this->localtax1_type = $obj->localtax1_type;
3012 $this->localtax2_type = $obj->localtax2_type;
3014 $this->finished = $obj->finished;
3015 $this->fk_default_bom = $obj->fk_default_bom;
3017 $this->duration = $obj->duration;
3019 preg_match(
'/(\d+)(\w+)/', $obj->duration, $matches);
3020 $this->duration_value = !empty($matches[1]) ? (int) $matches[1] : 0;
3021 $this->duration_unit = !empty($matches[2]) ? (string) $matches[2] :
null;
3022 $this->canvas = $obj->canvas;
3023 $this->net_measure = $obj->net_measure;
3024 $this->net_measure_units = $obj->net_measure_units;
3025 $this->weight = $obj->weight;
3026 $this->weight_units = $obj->weight_units;
3027 $this->length = $obj->length;
3028 $this->length_units = $obj->length_units;
3029 $this->width = $obj->width;
3030 $this->width_units = $obj->width_units;
3031 $this->height = $obj->height;
3032 $this->height_units = $obj->height_units;
3034 $this->surface = $obj->surface;
3035 $this->surface_units = $obj->surface_units;
3036 $this->volume = $obj->volume;
3037 $this->volume_units = $obj->volume_units;
3038 $this->barcode = $obj->barcode;
3039 $this->barcode_type = $obj->fk_barcode_type;
3041 $this->accountancy_code_buy = $obj->accountancy_code_buy;
3042 $this->accountancy_code_buy_intra = $obj->accountancy_code_buy_intra;
3043 $this->accountancy_code_buy_export = $obj->accountancy_code_buy_export;
3044 $this->accountancy_code_sell = $obj->accountancy_code_sell;
3045 $this->accountancy_code_sell_intra = $obj->accountancy_code_sell_intra;
3046 $this->accountancy_code_sell_export = $obj->accountancy_code_sell_export;
3048 $this->fk_default_warehouse = $obj->fk_default_warehouse;
3049 $this->fk_default_workstation = $obj->fk_default_workstation;
3050 $this->seuil_stock_alerte = $obj->seuil_stock_alerte;
3051 $this->desiredstock = $obj->desiredstock;
3052 $this->stock_reel = $obj->stock;
3053 $this->pmp = $obj->pmp;
3055 $this->date_creation = $obj->datec;
3056 $this->date_modification = $obj->tms;
3057 $this->import_key = $obj->import_key;
3058 $this->entity = $obj->entity;
3060 $this->ref_ext = $obj->ref_ext;
3061 $this->fk_price_expression = $obj->fk_price_expression;
3062 $this->fk_unit = $obj->fk_unit;
3063 $this->price_autogen = $obj->price_autogen;
3064 $this->model_pdf = $obj->model_pdf;
3065 $this->last_main_doc = $obj->last_main_doc;
3067 $this->mandatory_period = $obj->mandatory_period;
3069 $this->db->free($resql);
3081 $produit_multiprices_limit =
getDolGlobalInt(
'PRODUIT_MULTIPRICES_LIMIT');
3082 for ($i = 1; $i <= $produit_multiprices_limit; $i++) {
3083 $sql =
"SELECT price, price_ttc, price_min, price_min_ttc,";
3084 $sql .=
" price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid, recuperableonly";
3085 $sql .=
" ,price_label";
3086 $sql .=
" FROM ".$this->db->prefix().
"product_price";
3087 $sql .=
" WHERE entity IN (".getEntity(
'productprice').
")";
3088 $sql .=
" AND price_level=".((int) $i);
3089 $sql .=
" AND fk_product = ".((int) $this->
id);
3090 $sql .=
" ORDER BY date_price DESC, rowid DESC";
3092 $resql = $this->db->query($sql);
3094 $result = $this->db->fetch_array($resql);
3096 $this->multiprices[$i] = $result ? $result[
"price"] :
null;
3097 $this->multiprices_ttc[$i] = $result ? $result[
"price_ttc"] :
null;
3098 $this->multiprices_min[$i] = $result ? $result[
"price_min"] :
null;
3099 $this->multiprices_min_ttc[$i] = $result ? $result[
"price_min_ttc"] :
null;
3100 $this->multiprices_base_type[$i] = $result ? $result[
"price_base_type"] :
null;
3102 $this->multiprices_tva_tx[$i] = $result ? $result[
"tva_tx"].(!empty($result[
'default_vat_code']) ?
' ('.$result[
'default_vat_code'].
')' :
'') :
null;
3103 $this->multiprices_recuperableonly[$i] = $result ? $result[
"recuperableonly"] :
null;
3142 $this->error = $this->db->lasterror;
3148 } elseif (
getDolGlobalString(
'PRODUIT_CUSTOMER_PRICES_BY_QTY') && empty($ignore_price_load)) {
3149 $sql =
"SELECT price, price_ttc, price_min, price_min_ttc,";
3150 $sql .=
" price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid";
3151 $sql .=
" FROM ".$this->db->prefix().
"product_price";
3152 $sql .=
" WHERE fk_product = ".((int) $this->
id);
3153 $sql .=
" ORDER BY date_price DESC, rowid DESC";
3156 $resql = $this->db->query($sql);
3158 $result = $this->db->fetch_array($resql);
3162 $this->prices_by_qty[0] = $result[
"price_by_qty"];
3163 $this->prices_by_qty_id[0] = $result[
"rowid"];
3165 if ($this->prices_by_qty[0] == 1) {
3166 $sql =
"SELECT rowid,price, unitprice, quantity, remise_percent, remise, remise, price_base_type";
3167 $sql .=
" FROM ".$this->db->prefix().
"product_price_by_qty";
3168 $sql .=
" WHERE fk_product_price = ".((int) $this->prices_by_qty_id[0]);
3169 $sql .=
" ORDER BY quantity ASC";
3171 $resql = $this->db->query($sql);
3173 $resultat = array();
3175 while ($result = $this->db->fetch_array($resql)) {
3176 $resultat[$ii] = array();
3177 $resultat[$ii][
"rowid"] = $result[
"rowid"];
3178 $resultat[$ii][
"price"] = $result[
"price"];
3179 $resultat[$ii][
"unitprice"] = $result[
"unitprice"];
3180 $resultat[$ii][
"quantity"] = $result[
"quantity"];
3181 $resultat[$ii][
"remise_percent"] = $result[
"remise_percent"];
3183 $resultat[$ii][
"price_base_type"] = $result[
"price_base_type"];
3186 $this->prices_by_qty_list[0] = $resultat;
3188 $this->error = $this->db->lasterror;
3194 $this->error = $this->db->lasterror;
3197 } elseif (
getDolGlobalString(
'PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') && empty($ignore_price_load)) {
3198 $produit_multiprices_limit =
getDolGlobalInt(
'PRODUIT_MULTIPRICES_LIMIT');
3199 for ($i = 1; $i <= $produit_multiprices_limit; $i++) {
3200 $sql =
"SELECT price, price_ttc, price_min, price_min_ttc,";
3201 $sql .=
" price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid, recuperableonly";
3202 $sql .=
" FROM ".$this->db->prefix().
"product_price";
3203 $sql .=
" WHERE entity IN (".getEntity(
'productprice').
")";
3204 $sql .=
" AND price_level=".((int) $i);
3205 $sql .=
" AND fk_product = ".((int) $this->
id);
3206 $sql .=
" ORDER BY date_price DESC, rowid DESC";
3208 $resql = $this->db->query($sql);
3210 $this->error = $this->db->lasterror;
3212 } elseif ($result = $this->db->fetch_array($resql)) {
3213 $this->multiprices[$i] = (!empty($result[
"price"]) ? $result[
"price"] : 0);
3214 $this->multiprices_ttc[$i] = (!empty($result[
"price_ttc"]) ? $result[
"price_ttc"] : 0);
3215 $this->multiprices_min[$i] = (!empty($result[
"price_min"]) ? $result[
"price_min"] : 0);
3216 $this->multiprices_min_ttc[$i] = (!empty($result[
"price_min_ttc"]) ? $result[
"price_min_ttc"] : 0);
3217 $this->multiprices_base_type[$i] = (!empty($result[
"price_base_type"]) ? $result[
"price_base_type"] :
'');
3219 $this->multiprices_tva_tx[$i] = (!empty($result[
"tva_tx"]) ? $result[
"tva_tx"] : 0);
3220 $this->multiprices_recuperableonly[$i] = (!empty($result[
"recuperableonly"]) ? $result[
"recuperableonly"] : 0);
3223 $this->prices_by_qty[$i] = (!empty($result[
"price_by_qty"]) ? $result[
"price_by_qty"] : 0);
3224 $this->prices_by_qty_id[$i] = (!empty($result[
"rowid"]) ? $result[
"rowid"] : 0);
3226 if ($this->prices_by_qty[$i] == 1) {
3227 $sql =
"SELECT rowid, price, unitprice, quantity, remise_percent, remise, price_base_type";
3228 $sql .=
" FROM ".$this->db->prefix().
"product_price_by_qty";
3229 $sql .=
" WHERE fk_product_price = ".((int) $this->prices_by_qty_id[$i]);
3230 $sql .=
" ORDER BY quantity ASC";
3232 $resql = $this->db->query($sql);
3234 $resultat = array();
3236 while ($result = $this->db->fetch_array($resql)) {
3237 $resultat[$ii] = array();
3238 $resultat[$ii][
"rowid"] = $result[
"rowid"];
3239 $resultat[$ii][
"price"] = $result[
"price"];
3240 $resultat[$ii][
"unitprice"] = $result[
"unitprice"];
3241 $resultat[$ii][
"quantity"] = $result[
"quantity"];
3242 $resultat[$ii][
"remise_percent"] = $result[
"remise_percent"];
3243 $resultat[$ii][
"remise"] = $result[
"remise"];
3244 $resultat[$ii][
"price_base_type"] = $result[
"price_base_type"];
3247 $this->prices_by_qty_list[$i] = $resultat;
3249 $this->error = $this->db->lasterror;
3257 if (isModEnabled(
'dynamicprices') && !empty($this->fk_price_expression) && empty($ignore_expression)) {
3258 include_once DOL_DOCUMENT_ROOT.
'/product/dynamic_price/class/price_parser.class.php';
3260 $price_result = $priceparser->parseProduct($this);
3261 if ($price_result >= 0) {
3262 $this->
price = $price_result;
3264 $this->price_ttc = (float)
price2num($this->
price) * (1 + ($this->tva_tx / 100));
3265 $this->price_ttc = (float)
price2num($this->price_ttc,
'MU');
3271 $this->stock_warehouse = array();
3278 $this->error = $this->db->lasterror();
3293 global $user, $hookmanager, $action;
3297 foreach (array(
'toconsume',
'consumed',
'toproduce',
'produced') as $role) {
3298 $this->stats_mo[
'customers_'.$role] = 0;
3299 $this->stats_mo[
'nb_'.$role] = 0;
3300 $this->stats_mo[
'qty_'.$role] = 0;
3302 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,";
3303 $sql .=
" SUM(mp.qty) as qty";
3304 $sql .=
" FROM ".$this->db->prefix().
"mrp_mo as c";
3305 $sql .=
" INNER JOIN ".$this->db->prefix().
"mrp_production as mp ON mp.fk_mo=c.rowid";
3306 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3307 $sql .=
" INNER JOIN ".$this->db->prefix().
"societe_commerciaux as sc ON sc.fk_soc=c.fk_soc AND sc.fk_user = ".((int) $user->id);
3310 $sql .=
" c.entity IN (".getEntity(
'mo').
")";
3312 $sql .=
" AND mp.fk_product = ".((int) $this->
id);
3313 $sql .=
" AND mp.role ='".$this->db->escape($role).
"'";
3315 $sql .=
" AND c.fk_soc = ".((int) $socid);
3318 $result = $this->db->query($sql);
3320 $obj = $this->db->fetch_object($result);
3321 $this->stats_mo[
'customers_'.$role] = $obj->nb_customers ? $obj->nb_customers : 0;
3322 $this->stats_mo[
'nb_'.$role] = $obj->nb ? $obj->nb : 0;
3323 $this->stats_mo[
'qty_'.$role] = $obj->qty ?
price2num($obj->qty,
'MS') : 0;
3325 $this->error = $this->db->error();
3330 if (!empty($error)) {
3334 $parameters = array(
'socid' => $socid);
3335 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerMO', $parameters, $this, $action);
3337 $this->stats_mo = $hookmanager->resArray[
'stats_mo'];
3353 global $hookmanager, $action;
3357 $this->stats_bom[
'nb_toproduce'] = 0;
3358 $this->stats_bom[
'nb_toconsume'] = 0;
3359 $this->stats_bom[
'qty_toproduce'] = 0;
3360 $this->stats_bom[
'qty_toconsume'] = 0;
3362 $sql =
"SELECT COUNT(DISTINCT b.rowid) as nb_toproduce,";
3363 $sql .=
" SUM(b.qty) as qty_toproduce";
3364 $sql .=
" FROM ".$this->db->prefix().
"bom_bom as b";
3365 $sql .=
" INNER JOIN ".$this->db->prefix().
"bom_bomline as bl ON bl.fk_bom=b.rowid";
3367 $sql .=
" b.entity IN (".getEntity(
'bom').
")";
3368 $sql .=
" AND b.fk_product =".((int) $this->
id);
3369 $sql .=
" GROUP BY b.rowid";
3371 $result = $this->db->query($sql);
3373 $obj = $this->db->fetch_object($result);
3374 $this->stats_bom[
'nb_toproduce'] = !empty($obj->nb_toproduce) ? $obj->nb_toproduce : 0;
3375 $this->stats_bom[
'qty_toproduce'] = !empty($obj->qty_toproduce) ?
price2num($obj->qty_toproduce) : 0;
3377 $this->error = $this->db->error();
3381 $sql =
"SELECT COUNT(DISTINCT bl.rowid) as nb_toconsume,";
3382 $sql .=
" SUM(bl.qty) as qty_toconsume";
3383 $sql .=
" FROM ".$this->db->prefix().
"bom_bom as b";
3384 $sql .=
" INNER JOIN ".$this->db->prefix().
"bom_bomline as bl ON bl.fk_bom=b.rowid";
3386 $sql .=
" b.entity IN (".getEntity(
'bom').
")";
3387 $sql .=
" AND bl.fk_product =".((int) $this->
id);
3389 $result = $this->db->query($sql);
3391 $obj = $this->db->fetch_object($result);
3392 $this->stats_bom[
'nb_toconsume'] = !empty($obj->nb_toconsume) ? $obj->nb_toconsume : 0;
3393 $this->stats_bom[
'qty_toconsume'] = !empty($obj->qty_toconsume) ?
price2num($obj->qty_toconsume) : 0;
3395 $this->error = $this->db->error();
3399 if (!empty($error)) {
3403 $parameters = array(
'socid' => $socid);
3404 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerMO', $parameters, $this, $action);
3406 $this->stats_bom = $hookmanager->resArray[
'stats_bom'];
3422 global $user, $hookmanager, $action;
3424 $sql =
"SELECT COUNT(DISTINCT p.fk_soc) as nb_customers, COUNT(DISTINCT p.rowid) as nb,";
3425 $sql .=
" COUNT(pd.rowid) as nb_rows, SUM(pd.qty) as qty";
3426 $sql .=
" FROM ".$this->db->prefix().
"propaldet as pd";
3427 $sql .=
", ".$this->db->prefix().
"propal as p";
3428 $sql .=
", ".$this->db->prefix().
"societe as s";
3429 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3430 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3432 $sql .=
" WHERE p.rowid = pd.fk_propal";
3433 $sql .=
" AND p.fk_soc = s.rowid";
3434 $sql .=
" AND p.entity IN (".getEntity(
'propal').
")";
3435 $sql .=
" AND pd.fk_product = ".((int) $this->
id);
3436 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3437 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3441 $sql .=
" AND p.fk_soc = ".((int) $socid);
3444 $result = $this->db->query($sql);
3446 $obj = $this->db->fetch_object($result);
3447 $this->stats_propale[
'customers'] = $obj->nb_customers;
3448 $this->stats_propale[
'nb'] = $obj->nb;
3449 $this->stats_propale[
'rows'] = $obj->nb_rows;
3450 $this->stats_propale[
'qty'] = $obj->qty ? $obj->qty : 0;
3455 if (is_array($TFather) && !empty($TFather)) {
3456 foreach ($TFather as &$fatherData) {
3457 $pFather =
new Product($this->db);
3458 $pFather->id = $fatherData[
'id'];
3459 $qtyCoef = $fatherData[
'qty'];
3461 if ($fatherData[
'incdec']) {
3462 $pFather->load_stats_propale($socid);
3464 $this->stats_propale[
'customers'] += $pFather->stats_propale[
'customers'];
3465 $this->stats_propale[
'nb'] += $pFather->stats_propale[
'nb'];
3466 $this->stats_propale[
'rows'] += $pFather->stats_propale[
'rows'];
3467 $this->stats_propale[
'qty'] += $pFather->stats_propale[
'qty'] * $qtyCoef;
3473 $parameters = array(
'socid' => $socid);
3474 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerProposal', $parameters, $this, $action);
3476 $this->stats_propale = $hookmanager->resArray[
'stats_propale'];
3481 $this->error = $this->db->error();
3497 global $user, $hookmanager, $action;
3499 $sql =
"SELECT COUNT(DISTINCT p.fk_soc) as nb_suppliers, COUNT(DISTINCT p.rowid) as nb,";
3500 $sql .=
" COUNT(pd.rowid) as nb_rows, SUM(pd.qty) as qty";
3501 $sql .=
" FROM ".$this->db->prefix().
"supplier_proposaldet as pd";
3502 $sql .=
", ".$this->db->prefix().
"supplier_proposal as p";
3503 $sql .=
", ".$this->db->prefix().
"societe as s";
3504 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3505 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3507 $sql .=
" WHERE p.rowid = pd.fk_supplier_proposal";
3508 $sql .=
" AND p.fk_soc = s.rowid";
3509 $sql .=
" AND p.entity IN (".getEntity(
'supplier_proposal').
")";
3510 $sql .=
" AND pd.fk_product = ".((int) $this->
id);
3511 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3512 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3516 $sql .=
" AND p.fk_soc = ".((int) $socid);
3519 $result = $this->db->query($sql);
3521 $obj = $this->db->fetch_object($result);
3522 $this->stats_proposal_supplier[
'suppliers'] = $obj->nb_suppliers;
3523 $this->stats_proposal_supplier[
'nb'] = $obj->nb;
3524 $this->stats_proposal_supplier[
'rows'] = $obj->nb_rows;
3525 $this->stats_proposal_supplier[
'qty'] = $obj->qty ? $obj->qty : 0;
3527 $parameters = array(
'socid' => $socid);
3528 $reshook = $hookmanager->executeHooks(
'loadStatsSupplierProposal', $parameters, $this, $action);
3530 $this->stats_proposal_supplier = $hookmanager->resArray[
'stats_proposal_supplier'];
3535 $this->error = $this->db->error();
3553 global $user, $hookmanager, $action;
3555 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,";
3556 $sql .=
" COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty";
3557 $sql .=
" FROM ".$this->db->prefix().
"commandedet as cd";
3558 $sql .=
", ".$this->db->prefix().
"commande as c";
3559 $sql .=
", ".$this->db->prefix().
"societe as s";
3560 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3561 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3563 $sql .=
" WHERE c.rowid = cd.fk_commande";
3564 $sql .=
" AND c.fk_soc = s.rowid";
3565 $sql .=
" AND c.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'commande').
")";
3566 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
3567 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3568 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3571 $sql .=
" AND c.fk_soc = ".((int) $socid);
3573 if ($filtrestatut !=
'') {
3574 $sql .=
" AND c.fk_statut in (".$this->db->sanitize($filtrestatut).
")";
3577 $result = $this->db->query($sql);
3579 $obj = $this->db->fetch_object($result);
3580 $this->stats_commande[
'customers'] = $obj->nb_customers;
3581 $this->stats_commande[
'nb'] = $obj->nb;
3582 $this->stats_commande[
'rows'] = $obj->nb_rows;
3583 $this->stats_commande[
'qty'] = $obj->qty ? $obj->qty : 0;
3588 if (is_array($TFather) && !empty($TFather)) {
3589 foreach ($TFather as &$fatherData) {
3590 $pFather =
new Product($this->db);
3591 $pFather->id = $fatherData[
'id'];
3592 $qtyCoef = $fatherData[
'qty'];
3594 if ($fatherData[
'incdec']) {
3595 $pFather->load_stats_commande($socid, $filtrestatut);
3597 $this->stats_commande[
'customers'] += $pFather->stats_commande[
'customers'];
3598 $this->stats_commande[
'nb'] += $pFather->stats_commande[
'nb'];
3599 $this->stats_commande[
'rows'] += $pFather->stats_commande[
'rows'];
3600 $this->stats_commande[
'qty'] += $pFather->stats_commande[
'qty'] * $qtyCoef;
3612 $sql =
"SELECT SUM(".$this->db->ifsql(
'f.type=2', -1, 1).
" * fd.qty) as count FROM ".$this->db->prefix().
"facturedet as fd ";
3613 $sql .=
" JOIN ".$this->db->prefix().
"facture as f ON fd.fk_facture = f.rowid";
3614 $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'))";
3615 $sql .=
" JOIN ".$this->db->prefix().
"commande as c ON el.fk_source = c.rowid";
3616 $sql .=
" WHERE c.fk_statut IN (".$this->db->sanitize($filtrestatut).
") AND c.facture = 0 AND fd.fk_product = ".((int) $this->
id);
3618 dol_syslog(__METHOD__.
":: sql $sql", LOG_NOTICE);
3619 $resql = $this->db->query($sql);
3621 if ($this->db->num_rows($resql) > 0) {
3622 $obj = $this->db->fetch_object($resql);
3623 $adeduire += $obj->count;
3627 $this->stats_commande[
'qty'] -= $adeduire;
3630 include_once DOL_DOCUMENT_ROOT.
'/compta/facture/class/facture.class.php';
3634 $sql =
"SELECT sum(".$this->db->ifsql(
'f.type=2', -1, 1).
" * fd.qty) as count FROM ".MAIN_DB_PREFIX.
"facturedet as fd ";
3635 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"facture as f ON fd.fk_facture = f.rowid";
3636 $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'))";
3637 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"commande as c ON el.fk_source = c.rowid";
3638 $sql .=
" WHERE c.fk_statut IN (".$this->db->sanitize($filtrestatut).
") AND f.fk_statut > ".
Facture::STATUS_DRAFT.
" AND fd.fk_product = ".((int) $this->
id);
3640 dol_syslog(__METHOD__.
":: sql $sql", LOG_NOTICE);
3641 $resql = $this->db->query($sql);
3643 if ($this->db->num_rows($resql) > 0) {
3644 $obj = $this->db->fetch_object($resql);
3645 $adeduire += $obj->count;
3648 $this->error = $this->db->error();
3652 $this->stats_commande[
'qty'] -= $adeduire;
3656 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3657 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerOrder', $parameters, $this, $action);
3659 $this->stats_commande = $hookmanager->resArray[
'stats_commande'];
3663 $this->error = $this->db->error();
3681 global $user, $hookmanager, $action;
3683 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_suppliers, COUNT(DISTINCT c.rowid) as nb,";
3684 $sql .=
" COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty";
3685 $sql .=
" FROM ".$this->db->prefix().
"commande_fournisseurdet as cd";
3686 $sql .=
", ".$this->db->prefix().
"commande_fournisseur as c";
3687 $sql .=
", ".$this->db->prefix().
"societe as s";
3688 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3689 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3691 $sql .=
" WHERE c.rowid = cd.fk_commande";
3692 $sql .=
" AND c.fk_soc = s.rowid";
3693 $sql .=
" AND c.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'supplier_order').
")";
3694 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
3695 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3696 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3699 $sql .=
" AND c.fk_soc = ".((int) $socid);
3701 if ($filtrestatut !=
'') {
3702 $sql .=
" AND c.fk_statut in (".$this->db->sanitize($filtrestatut).
")";
3704 if (!empty($dateofvirtualstock)) {
3705 $sql .=
" AND c.date_livraison <= '".$this->db->idate($dateofvirtualstock).
"'";
3708 $result = $this->db->query($sql);
3710 $obj = $this->db->fetch_object($result);
3711 $this->stats_commande_fournisseur[
'suppliers'] = $obj->nb_suppliers;
3712 $this->stats_commande_fournisseur[
'nb'] = $obj->nb;
3713 $this->stats_commande_fournisseur[
'rows'] = $obj->nb_rows;
3714 $this->stats_commande_fournisseur[
'qty'] = $obj->qty ? $obj->qty : 0;
3716 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3717 $reshook = $hookmanager->executeHooks(
'loadStatsSupplierOrder', $parameters, $this, $action);
3719 $this->stats_commande_fournisseur = $hookmanager->resArray[
'stats_commande_fournisseur'];
3724 $this->error = $this->db->error().
' sql='.$sql;
3739 public function load_stats_sending($socid = 0, $filtrestatut =
'', $forVirtualStock = 0, $filterShipmentStatus =
'')
3742 global $user, $hookmanager, $action;
3744 $sql =
"SELECT COUNT(DISTINCT e.fk_soc) as nb_customers, COUNT(DISTINCT e.rowid) as nb,";
3745 $sql .=
" COUNT(ed.rowid) as nb_rows, SUM(ed.qty) as qty";
3746 $sql .=
" FROM ".$this->db->prefix().
"expeditiondet as ed";
3747 $sql .=
", ".$this->db->prefix().
"commandedet as cd";
3748 $sql .=
", ".$this->db->prefix().
"commande as c";
3749 $sql .=
", ".$this->db->prefix().
"expedition as e";
3750 $sql .=
", ".$this->db->prefix().
"societe as s";
3751 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3752 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3754 $sql .=
" WHERE e.rowid = ed.fk_expedition";
3755 $sql .=
" AND c.rowid = cd.fk_commande";
3756 $sql .=
" AND e.fk_soc = s.rowid";
3757 $sql .=
" AND e.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'expedition').
")";
3758 $sql .=
" AND ed.fk_elementdet = cd.rowid";
3759 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
3760 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3761 $sql .=
" AND e.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3764 $sql .=
" AND e.fk_soc = ".((int) $socid);
3766 if ($filtrestatut !=
'') {
3767 $sql .=
" AND c.fk_statut IN (".$this->db->sanitize($filtrestatut).
")";
3769 if (!empty($filterShipmentStatus)) {
3770 $sql .=
" AND e.fk_statut IN (".$this->db->sanitize($filterShipmentStatus).
")";
3773 $result = $this->db->query($sql);
3775 $obj = $this->db->fetch_object($result);
3776 $this->stats_expedition[
'customers'] = $obj->nb_customers;
3777 $this->stats_expedition[
'nb'] = $obj->nb;
3778 $this->stats_expedition[
'rows'] = $obj->nb_rows;
3779 $this->stats_expedition[
'qty'] = $obj->qty ? $obj->qty : 0;
3784 if (is_array($TFather) && !empty($TFather)) {
3785 foreach ($TFather as &$fatherData) {
3786 $pFather =
new Product($this->db);
3787 $pFather->id = $fatherData[
'id'];
3788 $qtyCoef = $fatherData[
'qty'];
3790 if ($fatherData[
'incdec']) {
3791 $pFather->load_stats_sending($socid, $filtrestatut, $forVirtualStock);
3793 $this->stats_expedition[
'customers'] += $pFather->stats_expedition[
'customers'];
3794 $this->stats_expedition[
'nb'] += $pFather->stats_expedition[
'nb'];
3795 $this->stats_expedition[
'rows'] += $pFather->stats_expedition[
'rows'];
3796 $this->stats_expedition[
'qty'] += $pFather->stats_expedition[
'qty'] * $qtyCoef;
3802 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock,
'filterShipmentStatus' => $filterShipmentStatus);
3803 $reshook = $hookmanager->executeHooks(
'loadStatsSending', $parameters, $this, $action);
3805 $this->stats_expedition = $hookmanager->resArray[
'stats_expedition'];
3810 $this->error = $this->db->error();
3825 public function load_stats_reception($socid = 0, $filtrestatut =
'', $forVirtualStock = 0, $dateofvirtualstock =
null)
3828 global $user, $hookmanager, $action;
3830 $sql =
"SELECT COUNT(DISTINCT cf.fk_soc) as nb_suppliers, COUNT(DISTINCT cf.rowid) as nb,";
3831 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(fd.qty) as qty";
3832 $sql .=
" FROM ".$this->db->prefix().
"receptiondet_batch as fd";
3833 $sql .=
", ".$this->db->prefix().
"commande_fournisseur as cf";
3834 $sql .=
", ".$this->db->prefix().
"societe as s";
3835 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3836 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3838 $sql .=
" WHERE cf.rowid = fd.fk_element";
3839 $sql .=
" AND cf.fk_soc = s.rowid";
3840 $sql .=
" AND cf.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'supplier_order').
")";
3841 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
3842 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3843 $sql .=
" AND cf.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3846 $sql .=
" AND cf.fk_soc = ".((int) $socid);
3848 if ($filtrestatut !=
'') {
3849 $sql .=
" AND cf.fk_statut IN (".$this->db->sanitize($filtrestatut).
")";
3851 if (!empty($dateofvirtualstock)) {
3852 $sql .=
" AND fd.datec <= '".$this->db->idate($dateofvirtualstock).
"'";
3855 $result = $this->db->query($sql);
3857 $obj = $this->db->fetch_object($result);
3858 $this->stats_reception[
'suppliers'] = $obj->nb_suppliers;
3859 $this->stats_reception[
'nb'] = $obj->nb;
3860 $this->stats_reception[
'rows'] = $obj->nb_rows;
3861 $this->stats_reception[
'qty'] = $obj->qty ? $obj->qty : 0;
3863 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3864 $reshook = $hookmanager->executeHooks(
'loadStatsReception', $parameters, $this, $action);
3866 $this->stats_reception = $hookmanager->resArray[
'stats_reception'];
3871 $this->error = $this->db->error();
3887 public function load_stats_inproduction($socid = 0, $filtrestatut =
'', $forVirtualStock = 0, $dateofvirtualstock =
null, $warehouseid = 0)
3890 global $user, $hookmanager, $action;
3892 $serviceStockIsEnabled = isModEnabled(
"service") &&
getDolGlobalString(
'STOCK_SUPPORTS_SERVICES');
3894 $sql =
"SELECT COUNT(DISTINCT m.fk_soc) as nb_customers, COUNT(DISTINCT m.rowid) as nb,";
3895 $sql .=
" COUNT(mp.rowid) as nb_rows, SUM(mp.qty) as qty, role";
3896 $sql .=
" FROM ".$this->db->prefix().
"mrp_production as mp";
3897 $sql .=
", ".$this->db->prefix().
"mrp_mo as m";
3898 $sql .=
" LEFT JOIN ".$this->db->prefix().
"societe as s ON s.rowid = m.fk_soc";
3899 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3900 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3902 $sql .=
" WHERE m.rowid = mp.fk_mo";
3903 $sql .=
" AND m.entity IN (".getEntity(($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE')) ?
'stock' :
'mrp').
")";
3904 $sql .=
" AND mp.fk_product = ".((int) $this->
id);
3905 $sql .=
" AND (mp.disable_stock_change IN (0) OR mp.disable_stock_change IS NULL)";
3906 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3907 $sql .=
" AND m.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3910 $sql .=
" AND m.fk_soc = ".((int) $socid);
3912 if ($filtrestatut !=
'') {
3913 $sql .=
" AND m.status IN (".$this->db->sanitize($filtrestatut).
")";
3915 if (!empty($dateofvirtualstock)) {
3916 $sql .=
" AND m.date_valid <= '".$this->db->idate($dateofvirtualstock).
"'";
3918 if (!$serviceStockIsEnabled) {
3919 $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))";
3921 if (!empty($warehouseid)) {
3922 $sql .=
" AND m.fk_warehouse = ".((int) $warehouseid);
3924 $sql .=
" GROUP BY role";
3927 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] = 0;
3929 $this->stats_mrptoconsume[
'customers'] = 0;
3930 $this->stats_mrptoconsume[
'nb'] = 0;
3931 $this->stats_mrptoconsume[
'rows'] = 0;
3932 $this->stats_mrptoconsume[
'qty'] = 0.0;
3933 $this->stats_mrptoproduce[
'customers'] = 0;
3934 $this->stats_mrptoproduce[
'nb'] = 0;
3935 $this->stats_mrptoproduce[
'rows'] = 0;
3936 $this->stats_mrptoproduce[
'qty'] = 0.0;
3939 $result = $this->db->query($sql);
3941 while ($obj = $this->db->fetch_object($result)) {
3942 if ($obj->role ==
'toconsume' && empty($warehouseid)) {
3943 $this->stats_mrptoconsume[
'customers'] += (int) $obj->nb_customers;
3944 $this->stats_mrptoconsume[
'nb'] += (int) $obj->nb;
3945 $this->stats_mrptoconsume[
'rows'] += (int) $obj->nb_rows;
3946 $this->stats_mrptoconsume[
'qty'] += ($obj->qty ? (float) $obj->qty : 0.0);
3948 if ($obj->role ==
'consumed' && empty($warehouseid)) {
3952 $this->stats_mrptoconsume[
'qty'] -= ($obj->qty ? (float) $obj->qty : 0.0);
3954 if ($obj->role ==
'toproduce') {
3956 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] += ($obj->qty ? (float) $obj->qty : 0.0);
3958 $this->stats_mrptoproduce[
'customers'] += (int) $obj->nb_customers;
3959 $this->stats_mrptoproduce[
'nb'] += (int) $obj->nb;
3960 $this->stats_mrptoproduce[
'rows'] += (int) $obj->nb_rows;
3961 $this->stats_mrptoproduce[
'qty'] += ($obj->qty ? (float) $obj->qty : 0.0);
3964 if ($obj->role ==
'produced') {
3969 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] -= ($obj->qty ? $obj->qty : 0);
3971 $this->stats_mrptoproduce[
'qty'] -= ($obj->qty ? $obj->qty : 0);
3978 if ($this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] < 0) {
3979 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] = 0;
3982 if ($this->stats_mrptoconsume[
'qty'] < 0) {
3983 $this->stats_mrptoconsume[
'qty'] = 0;
3985 if ($this->stats_mrptoproduce[
'qty'] < 0) {
3986 $this->stats_mrptoproduce[
'qty'] = 0;
3990 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3991 $reshook = $hookmanager->executeHooks(
'loadStatsInProduction', $parameters, $this, $action);
3993 $this->stats_mrptoproduce = $hookmanager->resArray[
'stats_mrptoproduce'];
3998 $this->error = $this->db->error();
4013 global $user, $hookmanager, $action;
4015 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,";
4016 $sql .=
" COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty";
4017 $sql .=
" FROM ".$this->db->prefix().
"contratdet as cd";
4018 $sql .=
", ".$this->db->prefix().
"contrat as c";
4019 $sql .=
", ".$this->db->prefix().
"societe as s";
4020 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4021 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4023 $sql .=
" WHERE c.rowid = cd.fk_contrat";
4024 $sql .=
" AND c.fk_soc = s.rowid";
4025 $sql .=
" AND c.entity IN (".getEntity(
'contract').
")";
4026 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
4027 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4028 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4032 $sql .=
" AND c.fk_soc = ".((int) $socid);
4035 $result = $this->db->query($sql);
4037 $obj = $this->db->fetch_object($result);
4038 $this->stats_contrat[
'customers'] = $obj->nb_customers;
4039 $this->stats_contrat[
'nb'] = $obj->nb;
4040 $this->stats_contrat[
'rows'] = $obj->nb_rows;
4041 $this->stats_contrat[
'qty'] = $obj->qty ? $obj->qty : 0;
4046 if (is_array($TFather) && !empty($TFather)) {
4047 foreach ($TFather as &$fatherData) {
4048 $pFather =
new Product($this->db);
4049 $pFather->id = $fatherData[
'id'];
4050 $qtyCoef = $fatherData[
'qty'];
4052 if ($fatherData[
'incdec']) {
4053 $pFather->load_stats_contrat($socid);
4055 $this->stats_contrat[
'customers'] += $pFather->stats_contrat[
'customers'];
4056 $this->stats_contrat[
'nb'] += $pFather->stats_contrat[
'nb'];
4057 $this->stats_contrat[
'rows'] += $pFather->stats_contrat[
'rows'];
4058 $this->stats_contrat[
'qty'] += $pFather->stats_contrat[
'qty'] * $qtyCoef;
4064 $parameters = array(
'socid' => $socid);
4065 $reshook = $hookmanager->executeHooks(
'loadStatsContract', $parameters, $this, $action);
4067 $this->stats_contrat = $hookmanager->resArray[
'stats_contrat'];
4072 $this->error = $this->db->error().
' sql='.$sql;
4087 global $user, $hookmanager, $action;
4089 $sql =
"SELECT COUNT(DISTINCT f.fk_soc) as nb_customers, COUNT(DISTINCT f.rowid) as nb,";
4090 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(".$this->db->ifsql(
'f.type != 2',
'fd.qty',
'fd.qty * -1').
") as qty";
4091 $sql .=
" FROM ".$this->db->prefix().
"facturedet as fd";
4092 $sql .=
", ".$this->db->prefix().
"facture as f";
4093 $sql .=
", ".$this->db->prefix().
"societe as s";
4094 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4095 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4097 $sql .=
" WHERE f.rowid = fd.fk_facture";
4098 $sql .=
" AND f.fk_soc = s.rowid";
4099 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4100 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
4101 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4102 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4106 $sql .=
" AND f.fk_soc = ".((int) $socid);
4109 $result = $this->db->query($sql);
4111 $obj = $this->db->fetch_object($result);
4112 $this->stats_facture[
'customers'] = $obj->nb_customers;
4113 $this->stats_facture[
'nb'] = $obj->nb;
4114 $this->stats_facture[
'rows'] = $obj->nb_rows;
4115 $this->stats_facture[
'qty'] = $obj->qty ? $obj->qty : 0;
4120 if (is_array($TFather) && !empty($TFather)) {
4121 foreach ($TFather as &$fatherData) {
4122 $pFather =
new Product($this->db);
4123 $pFather->id = $fatherData[
'id'];
4124 $qtyCoef = $fatherData[
'qty'];
4126 if ($fatherData[
'incdec']) {
4127 $pFather->load_stats_facture($socid);
4129 $this->stats_facture[
'customers'] += $pFather->stats_facture[
'customers'];
4130 $this->stats_facture[
'nb'] += $pFather->stats_facture[
'nb'];
4131 $this->stats_facture[
'rows'] += $pFather->stats_facture[
'rows'];
4132 $this->stats_facture[
'qty'] += $pFather->stats_facture[
'qty'] * $qtyCoef;
4138 $parameters = array(
'socid' => $socid);
4139 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerInvoice', $parameters, $this, $action);
4141 $this->stats_facture = $hookmanager->resArray[
'stats_facture'];
4146 $this->error = $this->db->error();
4162 global $user, $hookmanager, $action;
4164 $sql =
"SELECT COUNT(DISTINCT f.fk_soc) as nb_customers, COUNT(DISTINCT f.rowid) as nb,";
4165 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(fd.qty) as qty";
4166 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facturedet_rec as fd";
4167 $sql .=
", ".MAIN_DB_PREFIX.
"facture_rec as f";
4168 $sql .=
", ".MAIN_DB_PREFIX.
"societe as s";
4169 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4170 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
4172 $sql .=
" WHERE f.rowid = fd.fk_facture";
4173 $sql .=
" AND f.fk_soc = s.rowid";
4174 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4175 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
4176 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4177 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4181 $sql .=
" AND f.fk_soc = ".((int) $socid);
4184 $result = $this->db->query($sql);
4186 $obj = $this->db->fetch_object($result);
4187 $this->stats_facturerec[
'customers'] = (int) $obj->nb_customers;
4188 $this->stats_facturerec[
'nb'] = (int) $obj->nb;
4189 $this->stats_facturerec[
'rows'] = (int) $obj->nb_rows;
4190 $this->stats_facturerec[
'qty'] = $obj->qty ? (float) $obj->qty : 0.0;
4195 if (is_array($TFather) && !empty($TFather)) {
4196 foreach ($TFather as &$fatherData) {
4197 $pFather =
new Product($this->db);
4198 $pFather->id = $fatherData[
'id'];
4199 $qtyCoef = $fatherData[
'qty'];
4201 if ($fatherData[
'incdec']) {
4202 $pFather->load_stats_facture($socid);
4204 $this->stats_facturerec[
'customers'] += $pFather->stats_facturerec[
'customers'];
4205 $this->stats_facturerec[
'nb'] += $pFather->stats_facturerec[
'nb'];
4206 $this->stats_facturerec[
'rows'] += $pFather->stats_facturerec[
'rows'];
4207 $this->stats_facturerec[
'qty'] += $pFather->stats_facturerec[
'qty'] * $qtyCoef;
4213 $parameters = array(
'socid' => $socid);
4214 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerInvoiceRec', $parameters, $this, $action);
4216 $this->stats_facturerec = $hookmanager->resArray[
'stats_facturerec'];
4221 $this->error = $this->db->error();
4236 global $user, $hookmanager, $action;
4238 $sql =
"SELECT COUNT(DISTINCT f.fk_soc) as nb_suppliers, COUNT(DISTINCT f.rowid) as nb,";
4239 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(fd.qty) as qty";
4240 $sql .=
" FROM ".$this->db->prefix().
"facture_fourn_det as fd";
4241 $sql .=
", ".$this->db->prefix().
"facture_fourn as f";
4242 $sql .=
", ".$this->db->prefix().
"societe as s";
4243 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4244 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4246 $sql .=
" WHERE f.rowid = fd.fk_facture_fourn";
4247 $sql .=
" AND f.fk_soc = s.rowid";
4248 $sql .=
" AND f.entity IN (".getEntity(
'facture_fourn').
")";
4249 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
4250 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4251 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4255 $sql .=
" AND f.fk_soc = ".((int) $socid);
4258 $result = $this->db->query($sql);
4260 $obj = $this->db->fetch_object($result);
4261 $this->stats_facture_fournisseur[
'suppliers'] = (int) $obj->nb_suppliers;
4262 $this->stats_facture_fournisseur[
'nb'] = (int) $obj->nb;
4263 $this->stats_facture_fournisseur[
'rows'] = (int) $obj->nb_rows;
4264 $this->stats_facture_fournisseur[
'qty'] = $obj->qty ? (float) $obj->qty : 0.0;
4266 $parameters = array(
'socid' => $socid);
4267 $reshook = $hookmanager->executeHooks(
'loadStatsSupplierInvoice', $parameters, $this, $action);
4269 $this->stats_facture_fournisseur = $hookmanager->resArray[
'stats_facture_fournisseur'];
4274 $this->error = $this->db->error();
4293 $resql = $this->db->query($sql);
4295 $num = $this->db->num_rows($resql);
4298 $arr = $this->db->fetch_array($resql);
4299 if (is_array($arr)) {
4300 $keyfortab = (string) $arr[1];
4302 $keyfortab = substr($keyfortab, -2);
4305 if ($mode ==
'byunit') {
4306 $tab[$keyfortab] = (empty($tab[$keyfortab]) ? 0 : $tab[$keyfortab]) + $arr[0];
4307 } elseif ($mode ==
'bynumber') {
4308 $tab[$keyfortab] = (empty($tab[$keyfortab]) ? 0 : $tab[$keyfortab]) + $arr[2];
4309 } elseif ($mode ==
'byamount') {
4310 $tab[$keyfortab] = (empty($tab[$keyfortab]) ? 0 : $tab[$keyfortab]) + $arr[2];
4319 $this->error = $this->db->error().
' sql='.$sql;
4326 } elseif ($year == -1) {
4335 for ($j = 0; $j < 12; $j++) {
4337 $idx = ucfirst(
dol_trunc(
dol_print_date(
dol_mktime(12, 0, 0, $month, 1, 1970),
"%b"), 1,
'right',
'UTF-8', 1));
4340 $result[$j] = array($idx, isset($tab[$year.$month]) ? $tab[$year.$month] : 0);
4343 $month =
"0".($month - 1);
4345 $month = substr($month, 1);
4353 return array_reverse($result);
4368 public function get_nb_vente($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4373 $sql =
"SELECT sum(d.qty) as qty, date_format(f.datef, '%Y%m')";
4374 if ($mode ==
'bynumber') {
4375 $sql .=
", count(DISTINCT f.rowid)";
4377 $sql .=
", sum(d.total_ht) as total_ht";
4378 $sql .=
" FROM ".$this->db->prefix().
"facturedet as d, ".$this->db->prefix().
"facture as f, ".$this->db->prefix().
"societe as s";
4379 if ($filteronproducttype >= 0) {
4380 $sql .=
", ".$this->db->prefix().
"product as p";
4382 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4383 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4385 $sql .=
" WHERE f.rowid = d.fk_facture";
4386 if ($this->
id > 0) {
4387 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4389 $sql .=
" AND d.fk_product > 0";
4391 if ($filteronproducttype >= 0) {
4392 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4394 $sql .=
" AND f.fk_soc = s.rowid";
4395 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4396 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4397 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4400 $sql .=
" AND f.fk_soc = $socid";
4402 $sql .= $morefilter;
4403 $sql .=
" GROUP BY date_format(f.datef,'%Y%m')";
4404 $sql .=
" ORDER BY date_format(f.datef,'%Y%m') DESC";
4406 return $this->
_get_stats($sql, $mode, $year);
4421 public function get_nb_achat($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4426 $sql =
"SELECT sum(d.qty) as qty, date_format(f.datef, '%Y%m')";
4427 if ($mode ==
'bynumber') {
4428 $sql .=
", count(DISTINCT f.rowid)";
4430 $sql .=
", sum(d.total_ht) as total_ht";
4431 $sql .=
" FROM ".$this->db->prefix().
"facture_fourn_det as d, ".$this->db->prefix().
"facture_fourn as f, ".$this->db->prefix().
"societe as s";
4432 if ($filteronproducttype >= 0) {
4433 $sql .=
", ".$this->db->prefix().
"product as p";
4435 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4436 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4438 $sql .=
" WHERE f.rowid = d.fk_facture_fourn";
4439 if ($this->
id > 0) {
4440 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4442 $sql .=
" AND d.fk_product > 0";
4444 if ($filteronproducttype >= 0) {
4445 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4447 $sql .=
" AND f.fk_soc = s.rowid";
4448 $sql .=
" AND f.entity IN (".getEntity(
'facture_fourn').
")";
4449 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4450 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4453 $sql .=
" AND f.fk_soc = $socid";
4455 $sql .= $morefilter;
4456 $sql .=
" GROUP BY date_format(f.datef,'%Y%m')";
4457 $sql .=
" ORDER BY date_format(f.datef,'%Y%m') DESC";
4459 return $this->
_get_stats($sql, $mode, $year);
4473 public function get_nb_propal($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4478 $sql =
"SELECT sum(d.qty) as qty, date_format(p.datep, '%Y%m')";
4479 if ($mode ==
'bynumber') {
4480 $sql .=
", count(DISTINCT p.rowid)";
4482 $sql .=
", sum(d.total_ht) as total_ht";
4483 $sql .=
" FROM ".$this->db->prefix().
"propaldet as d, ".$this->db->prefix().
"propal as p, ".$this->db->prefix().
"societe as s";
4484 if ($filteronproducttype >= 0) {
4485 $sql .=
", ".$this->db->prefix().
"product as prod";
4487 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4488 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4490 $sql .=
" WHERE p.rowid = d.fk_propal";
4491 if ($this->
id > 0) {
4492 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4494 $sql .=
" AND d.fk_product > 0";
4496 if ($filteronproducttype >= 0) {
4497 $sql .=
" AND prod.rowid = d.fk_product AND prod.fk_product_type = ".((int) $filteronproducttype);
4499 $sql .=
" AND p.fk_soc = s.rowid";
4500 $sql .=
" AND p.entity IN (".getEntity(
'propal').
")";
4501 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4502 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4505 $sql .=
" AND p.fk_soc = ".((int) $socid);
4507 $sql .= $morefilter;
4508 $sql .=
" GROUP BY date_format(p.datep,'%Y%m')";
4509 $sql .=
" ORDER BY date_format(p.datep,'%Y%m') DESC";
4511 return $this->
_get_stats($sql, $mode, $year);
4530 $sql =
"SELECT sum(d.qty) as qty, date_format(p.date_valid, '%Y%m')";
4531 if ($mode ==
'bynumber') {
4532 $sql .=
", count(DISTINCT p.rowid)";
4534 $sql .=
", sum(d.total_ht) as total_ht";
4535 $sql .=
" FROM ".$this->db->prefix().
"supplier_proposaldet as d, ".$this->db->prefix().
"supplier_proposal as p, ".$this->db->prefix().
"societe as s";
4536 if ($filteronproducttype >= 0) {
4537 $sql .=
", ".$this->db->prefix().
"product as prod";
4539 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4540 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4542 $sql .=
" WHERE p.rowid = d.fk_supplier_proposal";
4543 if ($this->
id > 0) {
4544 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4546 $sql .=
" AND d.fk_product > 0";
4548 if ($filteronproducttype >= 0) {
4549 $sql .=
" AND prod.rowid = d.fk_product AND prod.fk_product_type = ".((int) $filteronproducttype);
4551 $sql .=
" AND p.fk_soc = s.rowid";
4552 $sql .=
" AND p.entity IN (".getEntity(
'supplier_proposal').
")";
4553 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4554 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4557 $sql .=
" AND p.fk_soc = ".((int) $socid);
4559 $sql .= $morefilter;
4560 $sql .=
" GROUP BY date_format(p.date_valid,'%Y%m')";
4561 $sql .=
" ORDER BY date_format(p.date_valid,'%Y%m') DESC";
4563 return $this->
_get_stats($sql, $mode, $year);
4577 public function get_nb_order($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4582 $sql =
"SELECT sum(d.qty) as qty, date_format(c.date_commande, '%Y%m')";
4583 if ($mode ==
'bynumber') {
4584 $sql .=
", count(DISTINCT c.rowid)";
4586 $sql .=
", sum(d.total_ht) as total_ht";
4587 $sql .=
" FROM ".$this->db->prefix().
"commandedet as d, ".$this->db->prefix().
"commande as c, ".$this->db->prefix().
"societe as s";
4588 if ($filteronproducttype >= 0) {
4589 $sql .=
", ".$this->db->prefix().
"product as p";
4591 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4592 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4594 $sql .=
" WHERE c.rowid = d.fk_commande";
4595 if ($this->
id > 0) {
4596 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4598 $sql .=
" AND d.fk_product > 0";
4600 if ($filteronproducttype >= 0) {
4601 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4603 $sql .=
" AND c.fk_soc = s.rowid";
4604 $sql .=
" AND c.entity IN (".getEntity(
'commande').
")";
4605 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4606 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4609 $sql .=
" AND c.fk_soc = ".((int) $socid);
4611 $sql .= $morefilter;
4612 $sql .=
" GROUP BY date_format(c.date_commande,'%Y%m')";
4613 $sql .=
" ORDER BY date_format(c.date_commande,'%Y%m') DESC";
4615 return $this->
_get_stats($sql, $mode, $year);
4634 $sql =
"SELECT sum(d.qty) as qty, date_format(c.date_commande, '%Y%m')";
4635 if ($mode ==
'bynumber') {
4636 $sql .=
", count(DISTINCT c.rowid)";
4638 $sql .=
", sum(d.total_ht) as total_ht";
4639 $sql .=
" FROM ".$this->db->prefix().
"commande_fournisseurdet as d, ".$this->db->prefix().
"commande_fournisseur as c, ".$this->db->prefix().
"societe as s";
4640 if ($filteronproducttype >= 0) {
4641 $sql .=
", ".$this->db->prefix().
"product as p";
4643 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4644 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4646 $sql .=
" WHERE c.rowid = d.fk_commande";
4647 if ($this->
id > 0) {
4648 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4650 $sql .=
" AND d.fk_product > 0";
4652 if ($filteronproducttype >= 0) {
4653 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4655 $sql .=
" AND c.fk_soc = s.rowid";
4656 $sql .=
" AND c.entity IN (".getEntity(
'supplier_order').
")";
4657 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4658 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4661 $sql .=
" AND c.fk_soc = ".((int) $socid);
4663 $sql .= $morefilter;
4664 $sql .=
" GROUP BY date_format(c.date_commande,'%Y%m')";
4665 $sql .=
" ORDER BY date_format(c.date_commande,'%Y%m') DESC";
4667 return $this->
_get_stats($sql, $mode, $year);
4681 public function get_nb_contract($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4686 $sql =
"SELECT sum(d.qty) as qty, date_format(c.date_contrat, '%Y%m')";
4687 if ($mode ==
'bynumber') {
4688 $sql .=
", count(DISTINCT c.rowid)";
4690 $sql .=
", sum(d.total_ht) as total_ht";
4691 $sql .=
" FROM ".$this->db->prefix().
"contratdet as d, ".$this->db->prefix().
"contrat as c, ".$this->db->prefix().
"societe as s";
4692 if ($filteronproducttype >= 0) {
4693 $sql .=
", ".$this->db->prefix().
"product as p";
4695 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4696 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4698 $sql .=
" WHERE c.entity IN (".getEntity(
'contract').
")";
4699 $sql .=
" AND c.rowid = d.fk_contrat";
4701 if ($this->
id > 0) {
4702 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4704 $sql .=
" AND d.fk_product > 0";
4706 if ($filteronproducttype >= 0) {
4707 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4709 $sql .=
" AND c.fk_soc = s.rowid";
4711 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4712 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4715 $sql .=
" AND c.fk_soc = ".((int) $socid);
4717 $sql .= $morefilter;
4718 $sql .=
" GROUP BY date_format(c.date_contrat,'%Y%m')";
4719 $sql .=
" ORDER BY date_format(c.date_contrat,'%Y%m') DESC";
4721 return $this->
_get_stats($sql, $mode, $year);
4735 public function get_nb_mos($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4740 $sql =
"SELECT sum(d.qty), date_format(d.date_valid, '%Y%m')";
4741 if ($mode ==
'bynumber') {
4742 $sql .=
", count(DISTINCT d.rowid)";
4744 $sql .=
" FROM ".$this->db->prefix().
"mrp_mo as d LEFT JOIN ".$this->db->prefix().
"societe as s ON d.fk_soc = s.rowid";
4745 if ($filteronproducttype >= 0) {
4746 $sql .=
", ".$this->db->prefix().
"product as p";
4748 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4749 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4752 $sql .=
" WHERE d.entity IN (".getEntity(
'mo').
")";
4753 $sql .=
" AND d.status > 0";
4755 if ($this->
id > 0) {
4756 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4758 $sql .=
" AND d.fk_product > 0";
4760 if ($filteronproducttype >= 0) {
4761 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4764 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4765 $sql .=
" AND d.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4768 $sql .=
" AND d.fk_soc = ".((int) $socid);
4770 $sql .= $morefilter;
4771 $sql .=
" GROUP BY date_format(d.date_valid,'%Y%m')";
4772 $sql .=
" ORDER BY date_format(d.date_valid,'%Y%m') DESC";
4774 return $this->
_get_stats($sql, $mode, $year);
4794 if (!is_numeric($id_pere)) {
4797 if (!is_numeric($id_fils)) {
4800 if (!is_numeric($incdec)) {
4810 $sql =
"SELECT fk_product_pere from ".$this->db->prefix().
"product_association";
4811 $sql .=
" WHERE fk_product_pere = ".((int) $id_fils).
" AND fk_product_fils = ".((int) $id_pere);
4812 if (!$this->db->query($sql)) {
4817 $sql =
"SELECT MAX(rang) as max_rank FROM ".$this->db->prefix().
"product_association";
4818 $sql .=
" WHERE fk_product_pere = ".((int) $id_pere);
4819 $resql = $this->db->query($sql);
4821 $obj = $this->db->fetch_object($resql);
4822 $rank = $obj->max_rank + 1;
4824 $sql =
"INSERT INTO ".$this->db->prefix().
"product_association(fk_product_pere,fk_product_fils,qty,incdec,rang)";
4825 $sql .=
" VALUES (".((int) $id_pere).
", ".((int) $id_fils).
", ".
price2num($qty,
'MS').
", ".((int) $incdec).
", ".((int) $rank).
")";
4826 if (! $this->db->query($sql)) {
4832 $result = $this->
call_trigger(
'PRODUCT_SUBPRODUCT_ADD', $user);
4834 $this->error = $this->db->lasterror();
4835 dol_syslog(get_class($this).
'::addSubproduct error='.$this->error, LOG_ERR);
4867 if (!is_numeric($id_pere)) {
4870 if (!is_numeric($id_fils)) {
4873 if (!is_numeric($incdec)) {
4876 if (!is_numeric($qty)) {
4880 $sql =
'UPDATE '.$this->db->prefix().
'product_association SET ';
4881 $sql .=
'qty = '.price2num($qty,
'MS');
4882 $sql .=
',incdec = '.((int) $incdec);
4883 $sql .=
' WHERE fk_product_pere = '.((int) $id_pere).
' AND fk_product_fils = '.((int) $id_fils);
4885 if (!$this->db->query($sql)) {
4891 $result = $this->
call_trigger(
'PRODUCT_SUBPRODUCT_UPDATE', $user);
4893 $this->error = $this->db->lasterror();
4894 dol_syslog(get_class($this).
'::updateSubproduct error='.$this->error, LOG_ERR);
4918 if (!is_numeric($fk_parent)) {
4921 if (!is_numeric($fk_child)) {
4925 $sql =
"DELETE FROM ".$this->db->prefix().
"product_association";
4926 $sql .=
" WHERE fk_product_pere = ".((int) $fk_parent);
4927 $sql .=
" AND fk_product_fils = ".((int) $fk_child);
4929 dol_syslog(get_class($this).
'::del_sousproduit', LOG_DEBUG);
4930 if (!$this->db->query($sql)) {
4936 $sqlrank =
"SELECT rowid, rang FROM ".$this->db->prefix().
"product_association";
4937 $sqlrank .=
" WHERE fk_product_pere = ".((int) $fk_parent);
4938 $sqlrank .=
" ORDER BY rang";
4939 $resqlrank = $this->db->query($sqlrank);
4942 while ($objrank = $this->db->fetch_object($resqlrank)) {
4944 $sql =
"UPDATE ".$this->db->prefix().
"product_association";
4945 $sql .=
" SET rang = ".((int) $cpt);
4946 $sql .=
" WHERE rowid = ".((int) $objrank->rowid);
4947 if (! $this->db->query($sql)) {
4956 $result = $this->
call_trigger(
'PRODUCT_SUBPRODUCT_DELETE', $user);
4958 $this->error = $this->db->lasterror();
4959 dol_syslog(get_class($this).
'::delSubproduct error='.$this->error, LOG_ERR);
4979 $sql =
"SELECT fk_product_pere, qty, incdec";
4980 $sql .=
" FROM ".$this->db->prefix().
"product_association";
4981 $sql .=
" WHERE fk_product_pere = ".((int) $fk_parent);
4982 $sql .=
" AND fk_product_fils = ".((int) $fk_child);
4984 $result = $this->db->query($sql);
4986 $num = $this->db->num_rows($result);
4989 $obj = $this->db->fetch_object($result);
4991 $this->is_sousproduit_qty = $obj->qty;
4992 $this->is_sousproduit_incdec = $obj->incdec;
5023 dol_syslog(get_class($this).
"::add_fournisseur id_fourn = ".$id_fourn.
" ref_fourn=".$ref_fourn.
" quantity=".$quantity, LOG_DEBUG);
5030 $sql =
"SELECT rowid, fk_product";
5031 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price";
5032 $sql .=
" WHERE fk_soc = ".((int) $id_fourn);
5033 $sql .=
" AND ref_fourn = '".$this->db->escape($ref_fourn).
"'";
5034 $sql .=
" AND fk_product <> ".((int) $this->
id);
5035 $sql .=
" AND entity IN (".getEntity(
'productsupplierprice').
")";
5037 $resql = $this->db->query($sql);
5039 $obj = $this->db->fetch_object($resql);
5042 $this->product_id_already_linked = $obj->fk_product;
5045 $this->db->free($resql);
5049 $sql =
"SELECT rowid";
5050 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price";
5051 $sql .=
" WHERE fk_soc = ".((int) $id_fourn);
5053 $sql .=
" AND ref_fourn = '".$this->db->escape($ref_fourn).
"'";
5055 $sql .=
" AND (ref_fourn = '' OR ref_fourn IS NULL)";
5057 $sql .=
" AND quantity = ".((float) $quantity);
5058 $sql .=
" AND fk_product = ".((int) $this->
id);
5059 $sql .=
" AND entity IN (".getEntity(
'productsupplierprice').
")";
5061 $resql = $this->db->query($sql);
5063 $obj = $this->db->fetch_object($resql);
5067 $sql =
"INSERT INTO ".$this->db->prefix().
"product_fournisseur_price(";
5070 $sql .=
", fk_product";
5072 $sql .=
", ref_fourn";
5073 $sql .=
", quantity";
5074 $sql .=
", fk_user";
5076 $sql .=
") VALUES (";
5077 $sql .=
"'".$this->db->idate($now).
"'";
5078 $sql .=
", ".((int)
$conf->entity);
5079 $sql .=
", ".((int) $this->
id);
5080 $sql .=
", ".((int) $id_fourn);
5081 $sql .=
", '".$this->db->escape($ref_fourn).
"'";
5082 $sql .=
", ".((float) $quantity);
5083 $sql .=
", ".((int) $user->id);
5087 if ($this->db->query($sql)) {
5088 $this->product_fourn_price_id = $this->db->last_insert_id($this->db->prefix().
"product_fournisseur_price");
5091 $this->error = $this->db->lasterror();
5096 $this->product_fourn_price_id = $obj->rowid;
5100 $this->error = $this->db->lasterror();
5119 $sql =
"SELECT DISTINCT p.fk_soc";
5120 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price as p";
5121 $sql .=
" WHERE p.fk_product = ".((int) $this->
id);
5122 $sql .=
" AND p.entity = ".((int)
$conf->entity);
5124 $result = $this->db->query($sql);
5126 $num = $this->db->num_rows($result);
5129 $obj = $this->db->fetch_object($result);
5130 $list[$i] = $obj->fk_soc;
5155 $sql =
"INSERT INTO ".$this->db->prefix().
"product_price (";
5157 $sql .=
", fk_product";
5158 $sql .=
", date_price";
5159 $sql .=
", price_level";
5161 $sql .=
", price_ttc";
5162 $sql .=
", price_min";
5163 $sql .=
", price_min_ttc";
5164 $sql .=
", price_base_type";
5165 $sql .=
", price_label";
5166 $sql .=
", default_vat_code";
5168 $sql .=
", recuperableonly";
5169 $sql .=
", localtax1_tx";
5170 $sql .=
", localtax1_type";
5171 $sql .=
", localtax2_tx";
5172 $sql .=
", localtax2_type";
5173 $sql .=
", fk_user_author";
5175 $sql .=
", price_by_qty";
5176 $sql .=
", fk_price_expression";
5177 $sql .=
", fk_multicurrency";
5178 $sql .=
", multicurrency_code";
5179 $sql .=
", multicurrency_tx";
5180 $sql .=
", multicurrency_price";
5181 $sql .=
", multicurrency_price_ttc";
5186 $sql .=
", '".$this->db->idate($now).
"'";
5187 $sql .=
", price_level";
5189 $sql .=
", price_ttc";
5190 $sql .=
", price_min";
5191 $sql .=
", price_min_ttc";
5192 $sql .=
", price_base_type";
5193 $sql .=
", price_label";
5194 $sql .=
", default_vat_code";
5196 $sql .=
", recuperableonly";
5197 $sql .=
", localtax1_tx";
5198 $sql .=
", localtax1_type";
5199 $sql .=
", localtax2_tx";
5200 $sql .=
", localtax2_type";
5201 $sql .=
", ".$user->id;
5203 $sql .=
", price_by_qty";
5204 $sql .=
", fk_price_expression";
5205 $sql .=
", fk_multicurrency";
5206 $sql .=
", multicurrency_code";
5207 $sql .=
", multicurrency_tx";
5208 $sql .=
", multicurrency_price";
5209 $sql .=
", multicurrency_price_ttc";
5210 $sql .=
" FROM ".$this->db->prefix().
"product_price ps";
5211 $sql .=
" WHERE fk_product = ".((int) $fromId);
5212 $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)";
5213 $sql .=
" ORDER BY date_price DESC";
5216 $resql = $this->db->query($sql);
5218 $this->db->rollback();
5222 $this->db->commit();
5239 $sql =
'INSERT INTO '.$this->db->prefix().
'product_association (fk_product_pere, fk_product_fils, qty, incdec)';
5240 $sql .=
" SELECT ".$toId.
", fk_product_fils, qty, incdec FROM ".$this->db->prefix().
"product_association";
5241 $sql .=
" WHERE fk_product_pere = ".((int) $fromId);
5243 dol_syslog(get_class($this).
'::clone_association', LOG_DEBUG);
5244 if (!$this->db->query($sql)) {
5245 $this->db->rollback();
5249 $this->db->commit();
5282 $sql =
"INSERT ".$this->db->prefix().
"product_fournisseur_price (";
5283 $sql .=
" datec, fk_product, fk_soc, price, quantity, fk_user, tva_tx)";
5284 $sql .=
" SELECT '".$this->db->idate($now).
"', ".((int) $toId).
", fk_soc, price, quantity, fk_user, tva_tx";
5285 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price";
5286 $sql .=
" WHERE fk_product = ".((int) $fromId);
5288 dol_syslog(get_class($this).
'::clone_fournisseurs', LOG_DEBUG);
5289 $resql = $this->db->query($sql);
5291 $this->db->rollback();
5294 $this->db->commit();
5312 public function fetch_prod_arbo($prod, $compl_path =
'', $multiply = 1, $level = 1, $id_parent = 0, $ignore_stock_load = 0)
5318 foreach ($prod as $id_product => $desc_pere) {
5319 if (is_array($desc_pere)) {
5320 $id = (!empty($desc_pere[0]) ? $desc_pere[0] :
'');
5321 $nb = (!empty($desc_pere[1]) ? $desc_pere[1] :
'');
5322 $type = (!empty($desc_pere[2]) ? $desc_pere[2] :
'');
5323 $label = (!empty($desc_pere[3]) ? $desc_pere[3] :
'');
5324 $incdec = (!empty($desc_pere[4]) ? $desc_pere[4] : 0);
5326 if ($multiply < 1) {
5331 if (is_null($tmpproduct)) {
5332 $tmpproduct =
new Product($this->db);
5334 $tmpproduct->fetch($id);
5336 if (empty($ignore_stock_load) && ($tmpproduct->isProduct() ||
getDolGlobalString(
'STOCK_SUPPORTS_SERVICES'))) {
5337 $tmpproduct->load_stock(
'nobatch,novirtual');
5340 $this->res[] = array(
5342 'id_parent' => $id_parent,
5343 'ref' => $tmpproduct->ref,
5345 'nb_total' => $nb * $multiply,
5346 'stock' => $tmpproduct->stock_reel,
5347 'stock_alert' => $tmpproduct->seuil_stock_alerte,
5349 'fullpath' => $compl_path.$label,
5351 'desiredstock' => $tmpproduct->desiredstock,
5353 'incdec' => $incdec,
5354 'entity' => $tmpproduct->entity
5358 if (isset($desc_pere[
'childs']) && is_array($desc_pere[
'childs'])) {
5360 $this->
fetch_prod_arbo($desc_pere[
'childs'], $compl_path.$desc_pere[3].
" -> ", $desc_pere[1] * $multiply, $level + 1, $id, $ignore_stock_load);
5378 $this->res = array();
5379 if (isset($this->sousprods) && is_array($this->sousprods)) {
5380 foreach ($this->sousprods as $prod_name => $desc_product) {
5381 if (is_array($desc_product)) {
5382 $this->
fetch_prod_arbo($desc_product,
"", $multiply, 1, $this->
id, $ignore_stock_load);
5401 $sql =
"SELECT COUNT(pa.rowid) as nb";
5402 $sql .=
" FROM ".$this->db->prefix().
"product_association as pa";
5404 $sql .=
" WHERE pa.fk_product_fils = ".((int) $this->
id).
" OR pa.fk_product_pere = ".((int) $this->
id);
5405 } elseif ($mode == -1) {
5406 $sql .=
" WHERE pa.fk_product_fils = ".((int) $this->
id);
5407 } elseif ($mode == 1) {
5408 $sql .=
" WHERE pa.fk_product_pere = ".((int) $this->
id);
5411 $resql = $this->db->query($sql);
5413 $obj = $this->db->fetch_object($resql);
5432 $sql =
"SELECT count(rowid) as nb FROM ".$this->db->prefix().
"product_attribute_combination WHERE fk_product_parent = ".((int) $this->
id);
5433 $sql .=
" AND entity IN (".getEntity(
'product').
")";
5435 $resql = $this->db->query($sql);
5437 $obj = $this->db->fetch_object($resql);
5454 if (isModEnabled(
'variants')) {
5455 $sql =
"SELECT rowid FROM ".$this->db->prefix().
"product_attribute_combination WHERE fk_product_child = ".((int) $this->
id).
" AND entity IN (".
getEntity(
'product').
")";
5457 $query = $this->db->query($sql);
5460 if (!$this->db->num_rows($query)) {
5481 $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";
5482 $sql .=
", p.tosell as status, p.tobuy as status_buy";
5483 $sql .=
" FROM ".$this->db->prefix().
"product_association as pa,";
5484 $sql .=
" ".$this->db->prefix().
"product as p";
5485 $sql .=
" WHERE p.rowid = pa.fk_product_pere";
5486 $sql .=
" AND pa.fk_product_fils = ".((int) $this->
id);
5488 $res = $this->db->query($sql);
5491 while ($record = $this->db->fetch_array($res)) {
5493 $prods[$record[
'id']] = array();
5494 $prods[$record[
'id']][
'id'] = $record[
'rowid'];
5495 $prods[$record[
'id']][
'ref'] = $record[
'ref'];
5496 $prods[$record[
'id']][
'label'] = $record[
'label'];
5497 $prods[$record[
'id']][
'qty'] = $record[
'qty'];
5498 $prods[$record[
'id']][
'incdec'] = $record[
'incdec'];
5499 $prods[$record[
'id']][
'fk_product_type'] = $record[
'fk_product_type'];
5500 $prods[$record[
'id']][
'entity'] = $record[
'entity'];
5501 $prods[$record[
'id']][
'status'] = $record[
'status'];
5502 $prods[$record[
'id']][
'status_buy'] = $record[
'status_buy'];
5521 public function getChildsArbo($id, $firstlevelonly = 0, $level = 1, $parents = array())
5523 global $alreadyfound;
5529 $sql =
"SELECT p.rowid, p.ref, p.label as label, p.fk_product_type,";
5530 $sql .=
" pa.qty as qty, pa.fk_product_fils as id, pa.incdec,";
5531 $sql .=
" pa.rowid as fk_association, pa.rang";
5532 $sql .=
" FROM ".$this->db->prefix().
"product as p,";
5533 $sql .=
" ".$this->db->prefix().
"product_association as pa";
5534 $sql .=
" WHERE p.rowid = pa.fk_product_fils";
5535 $sql .=
" AND pa.fk_product_pere = ".((int) $id);
5536 $sql .=
" AND pa.fk_product_fils <> ".((int) $id);
5537 $sql .=
" ORDER BY pa.rang";
5539 dol_syslog(get_class($this).
'::getChildsArbo id='.$id.
' level='.$level.
' parents='.(is_array($parents) ? implode(
',', $parents) : $parents), LOG_DEBUG);
5542 $alreadyfound = array($id => 1);
5549 $res = $this->db->query($sql);
5552 while ($rec = $this->db->fetch_array($res)) {
5553 if (!empty($alreadyfound[$rec[
'rowid']])) {
5554 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);
5555 if (in_array($rec[
'id'], $parents)) {
5559 $alreadyfound[$rec[
'rowid']] = 1;
5560 $prods[$rec[
'rowid']] = array(
5563 2 => $rec[
'fk_product_type'],
5564 3 => $this->db->escape($rec[
'label']),
5565 4 => $rec[
'incdec'],
5567 6 => $rec[
'fk_association'],
5572 if (empty($firstlevelonly)) {
5573 $parents[] = $rec[
'rowid'];
5574 $listofchilds = $this->
getChildsArbo($rec[
'rowid'], 0, $level + 1, $parents);
5575 foreach ($listofchilds as $keyChild => $valueChild) {
5576 $prods[$rec[
'rowid']][
'childs'][$keyChild] = $valueChild;
5600 foreach ($this->
getChildsArbo($this->
id) as $keyChild => $valueChild) {
5601 $parent[$this->label][$keyChild] = $valueChild;
5603 foreach ($parent as $key => $value) {
5604 $this->sousprods[$key] = $value;
5617 global
$conf, $langs, $user;
5619 $langs->loadLangs(array(
'products',
'other'));
5622 $nofetch = !empty($params[
'nofetch']);
5625 return [
'optimize' => $langs->trans(
"ShowProduct")];
5629 $permissiontoreadproduct = 0;
5630 if ($this->
type == self::TYPE_PRODUCT && $user->hasRight(
'product',
'read')) {
5631 $permissiontoreadproduct = 1;
5633 if ($this->
type == self::TYPE_SERVICE && $user->hasRight(
'service',
'read')) {
5634 $permissiontoreadproduct = 1;
5637 if (!empty($this->entity) && $permissiontoreadproduct) {
5638 $tmpphoto = $this->
show_photos(
'product', $conf->product->multidir_output[$this->entity], 1, 1, 0, 0, 0, 80, 0, 0, 0, 0,
'1');
5639 if ($this->nbphoto > 0) {
5640 $datas[
'photo'] =
'<div class="photointooltip floatright">'.
"\n" . $tmpphoto .
'</div>';
5645 $datas[
'picto'] =
img_picto(
'',
'product').
' <u class="paddingrightonly">'.$langs->trans(
"Product").
'</u>';
5647 $datas[
'picto'] =
img_picto(
'',
'service').
' <u class="paddingrightonly">'.$langs->trans(
"Service").
'</u>';
5649 if (isset($this->
status) && isset($this->status_buy)) {
5650 $datas[
'status'] =
' '.$this->getLibStatut(5, 0) .
' '.$this->getLibStatut(5, 1);
5653 if (!empty($this->
ref)) {
5654 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'ProductRef').
':</b> '.$this->ref;
5656 if (!empty($this->label)) {
5657 $datas[
'label'] =
'<br><b>'.$langs->trans(
'ProductLabel').
':</b> '.$this->label;
5660 if ($permissiontoreadproduct) {
5665 if (isModEnabled(
'productbatch')) {
5666 $langs->load(
"productbatch");
5667 $datas[
'batchstatus'] =
"<br><b>".$langs->trans(
"ManageLotSerial").
'</b>: '.$this->
getLibStatut(0, 2);
5670 if (isModEnabled(
'barcode')) {
5671 $datas[
'barcode'] =
'<br><b>'.$langs->trans(
'BarCode').
':</b> '.$this->barcode;
5675 if ($this->weight) {
5676 $datas[
'weight'] =
"<br><b>".$langs->trans(
"Weight").
'</b>: '.$this->weight.
' '.
measuringUnitString(0,
"weight", $this->weight_units);
5679 if ($this->length) {
5680 $labelsize .= ($labelsize ?
" - " :
"").
"<b>".$langs->trans(
"Length").
'</b>: '.$this->length.
' '.
measuringUnitString(0,
'size', $this->length_units);
5683 $labelsize .= ($labelsize ?
" - " :
"").
"<b>".$langs->trans(
"Width").
'</b>: '.$this->width.
' '.
measuringUnitString(0,
'size', $this->width_units);
5685 if ($this->height) {
5686 $labelsize .= ($labelsize ?
" - " :
"").
"<b>".$langs->trans(
"Height").
'</b>: '.$this->height.
' '.
measuringUnitString(0,
'size', $this->height_units);
5689 $datas[
'size'] =
"<br>".$labelsize;
5692 $labelsurfacevolume =
"";
5693 if ($this->surface) {
5694 $labelsurfacevolume .= ($labelsurfacevolume ?
" - " :
"").
"<b>".$langs->trans(
"Surface").
'</b>: '.$this->surface.
' '.
measuringUnitString(0,
'surface', $this->surface_units);
5696 if ($this->volume) {
5697 $labelsurfacevolume .= ($labelsurfacevolume ?
" - " :
"").
"<b>".$langs->trans(
"Volume").
'</b>: '.$this->volume.
' '.
measuringUnitString(0,
'volume', $this->volume_units);
5699 if ($labelsurfacevolume) {
5700 $datas[
'surface'] =
"<br>" . $labelsurfacevolume;
5703 if ($this->
isService() && !empty($this->duration_value)) {
5705 $datas[
'duration'] =
'<br><b>'.$langs->trans(
"Duration").
':</b> '.$this->duration_value;
5706 if ($this->duration_value > 1) {
5707 $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"));
5708 } elseif ($this->duration_value > 0) {
5709 $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"));
5711 $datas[
'duration'] .= (!empty($this->duration_unit) && isset($dur[$this->duration_unit]) ?
" ".$langs->trans($dur[$this->duration_unit]) :
'');
5713 if (empty($user->socid)) {
5714 if (!empty($this->pmp) && $this->pmp) {
5715 $datas[
'pmp'] =
"<br><b>".$langs->trans(
"PMPValue").
'</b>: '.
price($this->pmp, 0,
'', 1, -1, -1,
$conf->currency);
5718 if (isModEnabled(
'accounting')) {
5719 if ($this->
status && isset($this->accountancy_code_sell)) {
5720 include_once DOL_DOCUMENT_ROOT.
'/core/lib/accounting.lib.php';
5721 $selllabel =
'<br>';
5722 $selllabel .=
'<br><b>'.$langs->trans(
'ProductAccountancySellCode').
':</b> '.
length_accountg($this->accountancy_code_sell);
5723 $selllabel .=
'<br><b>'.$langs->trans(
'ProductAccountancySellIntraCode').
':</b> '.
length_accountg($this->accountancy_code_sell_intra);
5724 $selllabel .=
'<br><b>'.$langs->trans(
'ProductAccountancySellExportCode').
':</b> '.
length_accountg($this->accountancy_code_sell_export);
5725 $datas[
'accountancysell'] = $selllabel;
5727 if ($this->status_buy && isset($this->accountancy_code_buy)) {
5728 include_once DOL_DOCUMENT_ROOT.
'/core/lib/accounting.lib.php';
5730 if (empty($this->
status)) {
5731 $buylabel .=
'<br>';
5733 $buylabel .=
'<br><b>'.$langs->trans(
'ProductAccountancyBuyCode').
':</b> '.
length_accountg($this->accountancy_code_buy);
5734 $buylabel .=
'<br><b>'.$langs->trans(
'ProductAccountancyBuyIntraCode').
':</b> '.
length_accountg($this->accountancy_code_buy_intra);
5735 $buylabel .=
'<br><b>'.$langs->trans(
'ProductAccountancyBuyExportCode').
':</b> '.
length_accountg($this->accountancy_code_buy_export);
5736 $datas[
'accountancybuy'] = $buylabel;
5741 if (isModEnabled(
'category') && !$nofetch) {
5742 require_once DOL_DOCUMENT_ROOT .
'/categories/class/categorie.class.php';
5743 $form =
new Form($this->db);
5744 $datas[
'categories'] =
'<br>' . $form->showCategories($this->
id, Categorie::TYPE_PRODUCT, 1);
5764 public function getNomUrl($withpicto = 0, $option =
'', $maxlength = 0, $save_lastsearch_value = -1, $notooltip = 0, $morecss =
'', $add_label = 0, $sep =
' - ')
5766 global $langs, $hookmanager;
5768 include_once DOL_DOCUMENT_ROOT.
'/core/lib/product.lib.php';
5772 $newref = $this->ref;
5774 $newref =
dol_trunc($newref, $maxlength,
'middle');
5778 'objecttype' => ($this->
type == 1 ?
'service' :
'product'),
5779 'option' => $option,
5782 $classfortooltip =
'classfortooltip';
5785 $classfortooltip =
'classforajaxtooltip';
5786 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
5793 if (empty($notooltip)) {
5795 $label = $langs->trans(
"ShowProduct");
5796 $linkclose .=
' alt="'.dol_escape_htmltag($label, 1, 1).
'"';
5798 $linkclose .= ($label ?
' title="'.dol_escape_htmltag($label, 1, 1).
'"' :
' title="tocomplete"');
5799 $linkclose .= $dataparams.
' class="nowraponall '.$classfortooltip.($morecss ?
' '.$morecss :
'').
'"';
5801 $linkclose =
' class="nowraponall'.($morecss ?
' '.$morecss :
'').
'"';
5804 if ($option ==
'supplier' || $option ==
'category') {
5805 $url = DOL_URL_ROOT.
'/product/price_suppliers.php?id='.$this->id;
5806 } elseif ($option ==
'stock') {
5807 $url = DOL_URL_ROOT.
'/product/stock/product.php?id='.$this->id;
5808 } elseif ($option ==
'composition') {
5809 $url = DOL_URL_ROOT.
'/product/composition/card.php?id='.$this->id;
5811 $url = DOL_URL_ROOT.
'/product/card.php?id='.$this->id;
5814 if ($option !==
'nolink') {
5816 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
5817 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
5818 $add_save_lastsearch_values = 1;
5820 if ($add_save_lastsearch_values) {
5821 $url .=
'&save_lastsearch_values=1';
5825 $linkstart =
'<a href="'.$url.
'"';
5826 $linkstart .= $linkclose.
'>';
5829 $result .= $linkstart;
5832 $result .= (
img_object(($notooltip ?
'' : $label),
'product',
'class="paddingright"', 0, 0, $notooltip ? 0 : 1));
5835 $result .= (
img_object(($notooltip ?
'' : $label),
'service',
'class="paddingright"', 0, 0, $notooltip ? 0 : 1));
5838 $result .=
'<span class="aaa">'.dol_escape_htmltag($newref).
'</span>';
5839 $result .= $linkend;
5840 if ($withpicto != 2) {
5841 $result .= (($add_label && $this->label) ? $sep.dol_trunc($this->label, ($add_label > 1 ? $add_label : 0)) :
'');
5845 $hookmanager->initHooks(array(
'productdao'));
5846 $parameters = array(
'id' => $this->
id,
'getnomurl' => &$result,
'label' => &$label);
5847 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
5849 $result = $hookmanager->resPrint;
5851 $result .= $hookmanager->resPrint;
5868 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
5872 $langs->load(
"products");
5873 $outputlangs->load(
"products");
5880 $modelpath =
"core/modules/product/doc/";
5882 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
5898 return $this->
LibStatut($this->status_buy, $mode, $type);
5900 return $this->
LibStatut($this->status_batch, $mode, $type);
5903 return $this->
LibStatut($this->status_buy, $mode, $type);
5921 $labelStatus = $labelStatusShort =
'';
5923 $langs->load(
'products');
5924 if (isModEnabled(
'productbatch')) {
5925 $langs->load(
"productbatch");
5931 $label = ($status == 0 ? $langs->transnoentitiesnoconv(
'ProductStatusNotOnBatch') : ($status == 1 ? $langs->transnoentitiesnoconv(
'ProductStatusOnBatch') : $langs->transnoentitiesnoconv(
'ProductStatusOnSerial')));
5934 $label = ($status == 0 ? $langs->transnoentitiesnoconv(
'ProductStatusNotOnBatchShort') : ($status == 1 ? $langs->transnoentitiesnoconv(
'ProductStatusOnBatchShort') : $langs->transnoentitiesnoconv(
'ProductStatusOnSerialShort')));
5939 return dolGetStatus($langs->transnoentitiesnoconv(
'ProductStatusNotOnBatch'),
'',
'', empty($status) ?
'status5' :
'status4', 3,
'dot');
5945 return dolGetStatus($langs->transnoentitiesnoconv(
'Unknown'));
5949 $statuttrans = empty($status) ?
'status5' :
'status4';
5954 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusNotOnSellShort');
5955 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusNotOnSell');
5956 } elseif ($type == 1) {
5957 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusNotOnBuyShort');
5958 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusNotOnBuy');
5959 } elseif ($type == 2) {
5960 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusNotOnBatch');
5961 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusNotOnBatchShort');
5963 } elseif ($status == 1) {
5966 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusOnSellShort');
5967 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusOnSell');
5968 } elseif ($type == 1) {
5969 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusOnBuyShort');
5970 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusOnBuy');
5971 } elseif ($type == 2) {
5972 $labelStatus = ($status == 1 ? $langs->transnoentitiesnoconv(
'ProductStatusOnBatch') : $langs->transnoentitiesnoconv(
'ProductStatusOnSerial'));
5973 $labelStatusShort = ($status == 1 ? $langs->transnoentitiesnoconv(
'ProductStatusOnBatchShort') : $langs->transnoentitiesnoconv(
'ProductStatusOnSerialShort'));
5975 } elseif ($type == 2 && $status == 2) {
5976 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusOnSerial');
5977 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusOnSerialShort');
5981 return dolGetStatus($langs->transnoentitiesnoconv(
'Unknown'),
'',
'',
'status0', 0);
5983 return dolGetStatus($labelStatus, $labelStatusShort,
'', $statuttrans, $mode);
5997 $langs->load(
'products');
6000 if (isset($this->finished) && $this->finished >= 0) {
6001 $sql =
"SELECT label, code FROM ".$this->db->prefix().
"c_product_nature where code = ".((int) $this->finished).
" AND active=1";
6002 $resql = $this->db->query($sql);
6004 $this->error = $this->db->error().
' sql='.$sql;
6005 dol_syslog(__METHOD__.
' Error '.$this->error, LOG_ERR);
6007 } elseif ($this->db->num_rows($resql) > 0 && $res = $this->db->fetch_array($resql)) {
6008 $label = $langs->trans($res[
'label']);
6010 $this->db->free($resql);
6034 public function correct_stock($user, $id_entrepot, $nbpiece, $movement, $label =
'', $price = 0, $inventorycode =
'', $origin_element =
'', $origin_id =
null, $disablestockchangeforsubproduct = 0, $extrafields =
null)
6040 include_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
6046 $nbpiece = abs($nbpiece);
6049 $op[0] =
"+".trim((
string) $nbpiece);
6050 $op[1] =
"-".trim((
string) $nbpiece);
6053 $movementstock->setOrigin($origin_element, $origin_id);
6054 $result = $movementstock->_create($user, $this->
id, $id_entrepot, $op[$movement], $movement, $price, $label, $inventorycode,
'',
'',
'',
'',
false, 0, $disablestockchangeforsubproduct);
6058 $array_options = $extrafields->getOptionalsFromPost(
'stock_mouvement');
6059 $movementstock->array_options = $array_options;
6060 $movementstock->insertExtraFields();
6062 $this->db->commit();
6065 $this->error = $movementstock->error;
6066 $this->errors = $movementstock->errors;
6068 $this->db->rollback();
6097 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)
6103 include_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
6109 $nbpiece = abs($nbpiece);
6113 $op[0] =
"+".trim((
string) $nbpiece);
6114 $op[1] =
"-".trim((
string) $nbpiece);
6117 $movementstock->setOrigin($origin_element, $origin_id);
6118 $result = $movementstock->_create($user, $this->
id, $id_entrepot, $op[$movement], $movement, $price, $label, $inventorycode,
'', $dlc, $dluo, $lot,
false, 0, $disablestockchangeforsubproduct, 0, $force_update_batch);
6122 $array_options = $extrafields->getOptionalsFromPost(
'stock_mouvement');
6123 $movementstock->array_options = $array_options;
6124 $movementstock->insertExtraFields();
6126 $this->db->commit();
6129 $this->error = $movementstock->error;
6130 $this->errors = $movementstock->errors;
6132 $this->db->rollback();
6152 public function load_stock($option =
'', $includedraftpoforvirtual =
null, $dateofvirtualstock =
null)
6155 $this->stock_reel = 0;
6156 $this->stock_warehouse = array();
6157 $this->stock_theorique = 0;
6160 $warehouseStatus = array();
6161 if (preg_match(
'/warehouseclosed/', $option)) {
6164 if (preg_match(
'/warehouseopen/', $option)) {
6167 if (preg_match(
'/warehouseinternal/', $option)) {
6175 $sql =
"SELECT ps.rowid, ps.reel, ps.fk_entrepot";
6176 $sql .=
" FROM ".$this->db->prefix().
"product_stock as ps";
6177 $sql .=
", ".$this->db->prefix().
"entrepot as w";
6178 $sql .=
" WHERE w.entity IN (".getEntity(
'stock').
")";
6179 $sql .=
" AND w.rowid = ps.fk_entrepot";
6180 $sql .=
" AND ps.fk_product = ".((int) $this->
id);
6181 if (count($warehouseStatus)) {
6182 $sql .=
" AND w.statut IN (".$this->db->sanitize(implode(
',', $warehouseStatus)).
")";
6185 $sql .=
" ORDER BY ps.reel ".(getDolGlobalString(
'DO_NOT_TRY_TO_DEFRAGMENT_STOCKS_WAREHOUSE') ?
'DESC' :
'ASC');
6187 dol_syslog(get_class($this).
"::load_stock", LOG_DEBUG);
6188 $result = $this->db->query($sql);
6190 $num = $this->db->num_rows($result);
6194 $row = $this->db->fetch_object($result);
6195 $this->stock_warehouse[$row->fk_entrepot] =
new stdClass();
6196 $this->stock_warehouse[$row->fk_entrepot]->real = $row->reel;
6197 $this->stock_warehouse[$row->fk_entrepot]->id = $row->rowid;
6198 if ((!preg_match(
'/nobatch/', $option)) && $this->
hasbatch()) {
6199 $this->stock_warehouse[$row->fk_entrepot]->detail_batch =
Productbatch::findAll($this->db, $row->rowid, 1, $this->id);
6201 $this->stock_reel += $row->reel;
6204 $this->stock_reel = (float)
price2num($this->stock_reel,
'MS');
6206 $this->db->free($result);
6208 if (!preg_match(
'/novirtual/', $option)) {
6214 $this->error = $this->db->lasterror();
6233 global $hookmanager, $action;
6235 $stock_commande_client = 0;
6236 $stock_commande_fournisseur = 0;
6237 $stock_sending_client = 0;
6238 $stock_reception_fournisseur = 0;
6239 $stock_inproduction = 0;
6243 if (isModEnabled(
'order')) {
6248 $stock_commande_client = $this->stats_commande[
'qty'];
6250 if (isModEnabled(
"shipping")) {
6251 require_once DOL_DOCUMENT_ROOT.
'/expedition/class/expedition.class.php';
6252 $filterShipmentStatus =
'';
6262 $stock_sending_client = $this->stats_expedition[
'qty'];
6265 if (isModEnabled(
"supplier_order")) {
6266 $filterStatus =
getDolGlobalString(
'SUPPLIER_ORDER_STATUS_FOR_VIRTUAL_STOCK',
'3,4');
6267 if (isset($includedraftpoforvirtual)) {
6268 $filterStatus =
'0,1,2,'.$filterStatus;
6274 $stock_commande_fournisseur = $this->stats_commande_fournisseur[
'qty'];
6277 if (isModEnabled(
"supplier_order") || isModEnabled(
"supplier_invoice")) {
6278 $filterStatus =
'4';
6279 if (isset($includedraftpoforvirtual)) {
6280 $filterStatus =
'0,'.$filterStatus;
6286 $stock_reception_fournisseur = $this->stats_reception[
'qty'];
6289 if (isModEnabled(
'mrp')) {
6294 $stock_inproduction = $this->stats_mrptoproduce[
'qty'] - $this->stats_mrptoconsume[
'qty'];
6297 $this->stock_theorique = $this->stock_reel + $stock_inproduction;
6301 $this->stock_theorique -= ($stock_commande_client - $stock_sending_client);
6303 $this->stock_theorique += 0;
6305 $this->stock_theorique -= $stock_commande_client;
6309 $this->stock_theorique += ($stock_commande_fournisseur - $stock_reception_fournisseur);
6311 $this->stock_theorique += ($stock_commande_fournisseur - $stock_reception_fournisseur);
6313 $this->stock_theorique -= $stock_reception_fournisseur;
6315 $this->stock_theorique += ($stock_commande_fournisseur - $stock_reception_fournisseur);
6318 $parameters = array(
'id' => $this->
id,
'includedraftpoforvirtual' => $includedraftpoforvirtual);
6320 $reshook = $hookmanager->executeHooks(
'loadvirtualstock', $parameters, $this, $action);
6322 $this->stock_theorique = $hookmanager->resArray[
'stock_theorique'];
6323 } elseif ($reshook == 0 && isset($hookmanager->resArray[
'stock_stats_hook'])) {
6324 $this->stock_theorique += $hookmanager->resArray[
'stock_stats_hook'];
6328 if (!empty($this->stock_warehouse) &&
getDolGlobalString(
'STOCK_ALLOW_VIRTUAL_STOCK_PER_WAREHOUSE')) {
6329 foreach ($this->stock_warehouse as $warehouseid => $stockwarehouse) {
6330 if (isModEnabled(
'mrp')) {
6337 if ($this->fk_default_warehouse == $warehouseid) {
6338 $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']);
6340 $this->stock_warehouse[$warehouseid]->virtual = $this->stock_warehouse[$warehouseid]->real + $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'];
6360 $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";
6361 $sql .=
" WHERE pb.fk_product_stock = ps.rowid AND ps.fk_product = ".((int) $this->
id).
" AND pb.batch = '".$this->db->escape($batch).
"'";
6362 $sql .=
" GROUP BY pb.batch, pb.eatby, pb.sellby";
6363 dol_syslog(get_class($this).
"::loadBatchInfo load first entry found for lot/serial = ".$batch, LOG_DEBUG);
6364 $resql = $this->db->query($sql);
6366 $num = $this->db->num_rows($resql);
6369 $obj = $this->db->fetch_object($resql);
6370 $result[] = array(
'batch' => $batch,
'eatby' => $this->db->jdate($obj->eatby),
'sellby' => $this->db->jdate($obj->sellby),
'qty' => $obj->qty);
6376 $this->db->rollback();
6393 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6399 $dir .=
'/'.get_exdir($this->
id, 2, 0, 0, $this,
'product').$this->id.
"/photos";
6401 $dir .=
'/'.get_exdir(0, 0, 0, 0, $this,
'product').dol_sanitizeFileName($this->
ref);
6406 $dir_osencoded = $dir;
6408 if (is_dir($dir_osencoded)) {
6409 $originImage = $dir.
'/'.$file[
'name'];
6420 if (is_numeric($result) && $result > 0) {
6437 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6438 include_once DOL_DOCUMENT_ROOT.
'/core/lib/images.lib.php';
6442 $dir .=
'/'.get_exdir($this->
id, 2, 0, 0, $this,
'product').$this->id.
"/photos/";
6444 $dir .=
'/'.get_exdir(0, 0, 0, 0, $this,
'product');
6448 if (file_exists($dir_osencoded)) {
6449 $handle = opendir($dir_osencoded);
6450 if (is_resource($handle)) {
6451 while (($file = readdir($handle)) !==
false) {
6453 $file = mb_convert_encoding($file,
'UTF-8',
'ISO-8859-1');
6476 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6477 include_once DOL_DOCUMENT_ROOT.
'/core/lib/images.lib.php';
6483 $handle = @opendir($dir_osencoded);
6484 if (is_resource($handle)) {
6485 while (($file = readdir($handle)) !==
false) {
6487 $file = mb_convert_encoding($file,
'UTF-8',
'ISO-8859-1');
6494 $photo_vignette =
'';
6496 if (preg_match(
'/('.$this->regeximgext.
')$/i', $photo, $regs)) {
6497 $photo_vignette = preg_replace(
'/'.$regs[0].
'/i',
'', $photo).
'_small'.$regs[0];
6500 $dirthumb = $dir.
'thumbs/';
6504 $obj[
'photo'] = $photo;
6505 if ($photo_vignette &&
dol_is_file($dirthumb.$photo_vignette)) {
6506 $obj[
'photo_vignette'] =
'thumbs/'.$photo_vignette;
6508 $obj[
'photo_vignette'] =
"";
6511 $tabobj[$nbphoto - 1] = $obj;
6514 if ($nbmax && $nbphoto >= $nbmax) {
6536 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6537 include_once DOL_DOCUMENT_ROOT.
'/core/lib/images.lib.php';
6539 $dir = dirname($file).
'/';
6540 $dirthumb = $dir.
'/thumbs/';
6541 $filename = preg_replace(
'/'.preg_quote($dir,
'/').
'/i',
'', $file);
6547 if (preg_match(
'/('.$this->regeximgext.
')$/i', $filename, $regs)) {
6548 $photo_vignette = preg_replace(
'/'.$regs[0].
'/i',
'', $filename).
'_small'.$regs[0];
6549 if (file_exists(
dol_osencode($dirthumb.$photo_vignette))) {
6553 $photo_vignette = preg_replace(
'/'.$regs[0].
'/i',
'', $filename).
'_mini'.$regs[0];
6554 if (file_exists(
dol_osencode($dirthumb.$photo_vignette))) {
6571 $infoImg = getimagesize($file_osencoded);
6572 $this->imgWidth = $infoImg[0];
6573 $this->imgHeight = $infoImg[1];
6583 global $hookmanager;
6585 $this->nb = array();
6587 $sql =
"SELECT count(p.rowid) as nb, fk_product_type";
6588 $sql .=
" FROM ".$this->db->prefix().
"product as p";
6589 $sql .=
' WHERE p.entity IN ('.getEntity($this->element, 1).
')';
6591 if (is_object($hookmanager)) {
6592 $parameters = array();
6593 $reshook = $hookmanager->executeHooks(
'printFieldListWhere', $parameters, $this);
6594 $sql .= $hookmanager->resPrint;
6596 $sql .=
' GROUP BY fk_product_type';
6598 $resql = $this->db->query($sql);
6600 while ($obj = $this->db->fetch_object($resql)) {
6601 if ($obj->fk_product_type == 1) {
6602 $this->nb[
"services"] = $obj->nb;
6604 $this->nb[
"products"] = $obj->nb;
6607 $this->db->free($resql);
6611 $this->error = $this->db->error();
6653 return $this->mandatory_period == 1;
6663 return $this->status_batch > 0;
6683 $dirsociete = array_merge(array(
'/core/modules/barcode/'),
$conf->modules_parts[
'barcode']);
6684 foreach ($dirsociete as $dirroot) {
6692 '@phan-var-force ModeleNumRefBarCode $mod';
6694 $result = $mod->getNextValue(
$object, $type);
6696 dol_syslog(get_class($this).
"::get_barcode barcode=".$result.
" module=".$var);
6713 $this->specimen = 1;
6715 $this->
ref =
'PRODUCT_SPEC';
6716 $this->label =
'PRODUCT SPECIMEN';
6717 $this->
description =
'This is description of this product specimen that was created the '.dol_print_date($now,
'dayhourlog').
'.';
6718 $this->specimen = 1;
6719 $this->country_id = 1;
6721 $this->status_buy = 1;
6723 $this->sell_or_eat_by_mandatory = 0;
6724 $this->note_private =
'This is a comment (private)';
6725 $this->note_public =
'This is a comment (public)';
6726 $this->date_creation = $now;
6727 $this->date_modification = $now;
6730 $this->weight_units = 3;
6733 $this->length_units = 1;
6735 $this->width_units = 0;
6736 $this->height =
null;
6737 $this->height_units =
null;
6739 $this->surface = 30;
6740 $this->surface_units = 0;
6741 $this->volume = 300;
6742 $this->volume_units = 0;
6744 $this->barcode = -1;
6759 if (!$this->fk_unit) {
6763 $langs->load(
'products');
6765 $label_type =
'label';
6766 if ($type ==
'short') {
6767 $label_type =
'short_label';
6770 $sql =
"SELECT ".$label_type.
", code from ".$this->db->prefix().
"c_units where rowid = ".((int) $this->fk_unit);
6772 $resql = $this->db->query($sql);
6774 $this->error = $this->db->error();
6775 dol_syslog(get_class($this).
"::getLabelOfUnit Error ".$this->error, LOG_ERR);
6777 } elseif ($this->db->num_rows($resql) > 0 && $res = $this->db->fetch_array($resql)) {
6778 $label = ($label_type ==
'short_label' ? $res[$label_type] :
'unit'.$res[
'code']);
6780 $this->db->free($resql);
6794 $maxpricesupplier = 0;
6797 include_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
6799 $product_fourn_list = $product_fourn->list_product_fournisseur_price($this->
id,
'',
'');
6801 if (is_array($product_fourn_list) && count($product_fourn_list) > 0) {
6802 foreach ($product_fourn_list as $productfourn) {
6803 if ($productfourn->fourn_unitprice > $maxpricesupplier) {
6804 $maxpricesupplier = $productfourn->fourn_unitprice;
6812 return $maxpricesupplier;
6828 require_once DOL_DOCUMENT_ROOT.
'/categories/class/categorie.class.php';
6829 return parent::setCategoriesCommon($categories, Categorie::TYPE_PRODUCT);
6843 'product_customer_price',
6844 'product_customer_price_log'
6863 $sql =
"SELECT rowid, level, fk_level, var_percent, var_min_percent FROM ".$this->db->prefix().
"product_pricerules";
6864 $query = $this->db->query($sql);
6868 while ($result = $this->db->fetch_object($query)) {
6869 $rules[$result->level] = $result;
6878 for ($i = 1; $i <= $nbofproducts; $i++) {
6879 $price = $baseprice;
6880 $price_min = $baseprice;
6884 if ($i > 1 && isset($rules[$i]->var_percent) && $rules[$i]->var_percent) {
6885 $price = $prices[$rules[$i]->fk_level] * (1 + ($rules[$i]->var_percent / 100));
6888 $prices[$i] = $price;
6891 if (isset($rules[$i]->var_min_percent) && $rules[$i]->var_min_percent) {
6892 $price_min = $price * (1 - ($rules[$i]->var_min_percent / 100));
6896 $check_amount = (($price == $this->multiprices[$i]) && ($price_min == $this->multiprices_min[$i]));
6897 $check_type = ($baseprice == $this->multiprices_base_type[$i]);
6899 if ($check_amount && $check_type) {
6903 if ($this->
updatePrice($price, $price_type, $user, $price_vat, $price_min, $i, $npr, $psq, 1) < 0) {
6921 return $user->rights->produit;
6923 return $user->rights->service;
6935 $sql =
"SELECT p.rowid, p.ref, p.datec as date_creation, p.tms as date_modification,";
6936 $sql .=
" p.fk_user_author, p.fk_user_modif";
6937 $sql .=
" FROM ".$this->db->prefix().$this->table_element.
" as p";
6938 $sql .=
" WHERE p.rowid = ".((int) $id);
6940 $result = $this->db->query($sql);
6942 if ($this->db->num_rows($result)) {
6943 $obj = $this->db->fetch_object($result);
6945 $this->
id = $obj->rowid;
6946 $this->
ref = $obj->ref;
6948 $this->user_creation_id = $obj->fk_user_author;
6949 $this->user_modification_id = $obj->fk_user_modif;
6951 $this->date_creation = $this->db->jdate($obj->date_creation);
6952 $this->date_modification = $this->db->jdate($obj->date_modification);
6955 $this->db->free($result);
6969 if (empty($this->duration_value)) {
6970 $this->errors[] =
'ErrorDurationForServiceNotDefinedCantCalculateHourlyPrice';
6973 if ($this->duration_unit ==
's') {
6974 $prodDurationHours = 1. / 3600;
6975 } elseif ($this->duration_unit ==
'i' || $this->duration_unit ==
'mn' || $this->duration_unit ==
'min') {
6976 $prodDurationHours = 1. / 60;
6977 } elseif ($this->duration_unit ==
'h') {
6978 $prodDurationHours = 1.;
6979 } elseif ($this->duration_unit ==
'd') {
6980 $prodDurationHours = 24.;
6981 } elseif ($this->duration_unit ==
'w') {
6982 $prodDurationHours = 24. * 7;
6983 } elseif ($this->duration_unit ==
'm') {
6984 $prodDurationHours = 24. * 30;
6985 } elseif ($this->duration_unit ==
'y') {
6986 $prodDurationHours = 24. * 365;
6988 $prodDurationHours = 0.0;
6990 $prodDurationHours *= $this->duration_value;
6992 return $prodDurationHours;
7005 global $langs,
$conf;
7007 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
7009 $return =
'<div class="box-flex-item box-flex-grow-zero">';
7010 $return .=
'<div class="info-box info-box-sm">';
7011 $return .=
'<div class="info-box-img">';
7014 $label .= $this->
show_photos(
'product', $conf->product->multidir_output[$this->entity], 1, 1, 0, 0, 0, 120, 160, 0, 0, 0,
'',
'photoref photokanban');
7024 $return .=
'</div>';
7025 $return .=
'<div class="info-box-content">';
7026 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this,
'getNomUrl') ? $this->
getNomUrl() : $this->ref).
'</span>';
7027 if ($selected >= 0) {
7028 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
7030 if (property_exists($this,
'label')) {
7031 $return .=
'<br><span class="info-box-label opacitymedium inline-block tdoverflowmax150 valignmiddle" title="'.dol_escape_htmltag($this->label).
'">'.
dol_escape_htmltag($this->label).
'</span>';
7033 if (property_exists($this,
'price') && property_exists($this,
'price_ttc')) {
7034 if ($this->price_base_type ==
'TTC') {
7035 $return .=
'<br><span class="info-box-status amount">'.price($this->price_ttc).
' '.$langs->trans(
"TTC").
'</span>';
7038 $return .=
'<br><span class="info-box-status amount">'.price($this->
price).
' '.$langs->trans(
"HT").
'</span>';
7043 if (property_exists($this,
'stock_reel') && $this->
isProduct()) {
7044 $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>';
7047 if (method_exists($this,
'getLibStatut')) {
7049 $return .=
'<br><div class="info-box-status inline-block valignmiddle">'.$this->getLibStatut(3, 1).
' '.$this->
getLibStatut(3, 0).
'</div>';
7051 $return .=
'<div class="info-box-status inline-block valignmiddle marginleftonly paddingleft">'.$this->getLibStatut(3, 1).
' '.$this->
getLibStatut(3, 0).
'</div>';
7054 $return .=
'</div>';
7055 $return .=
'</div>';
7056 $return .=
'</div>';
7069 if (!is_numeric($limit)) {
7073 $sql =
"SELECT p.rowid, p.ref, p.label, p.description, p.entity, ef.filename
7074 FROM ".MAIN_DB_PREFIX.
"product AS p
7075 JOIN ".MAIN_DB_PREFIX.
"ecm_files AS ef ON p.rowid = ef.src_object_id
7076 WHERE ef.entity IN (".
getEntity(
'product').
")
7077 AND (ef.filename LIKE '%.png' OR ef.filename LIKE '%.jpeg' OR ef.filename LIKE '%.svg')
7078 GROUP BY p.rowid, p.ref, p.label, p.description, p.entity, ef.filename
7079 ORDER BY p.datec ASC
7080 LIMIT " . ((int) $limit);
7082 $resql = $this->db->query($sql);
7083 $products = array();
7086 while ($obj = $this->db->fetch_object($resql)) {
7087 $products[] = array(
7088 'rowid' => $obj->rowid,
7090 'label' => $obj->label,
7091 'description' => $obj->description,
7092 'entity' => $obj->entity,
7093 'filename' => $obj->filename
7099 if (empty($products)) {
7112 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.
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_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_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0, $indexdatabase=1, $nolog=0, $level=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories)
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.
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)
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_clone($object, $native=2)
Create a clone of instance of object (new instance with same value for each properties) With native =...
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.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
measuring_units_squared($unitscale)
Transform a given unit scale into the square of that unit, if known.
measuringUnitString($unitid, $measuring_style='', $unitscale='', $use_short_label=0, $outputlangs=null)
Return translation label of a unit key.
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