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' ),
86 'bom_bom' => array(
'name' =>
'BOM'),
87 'bom_bomline' => array(
'name' =>
'BOMLine',
'parent' =>
'bom_bom',
'parentkey' =>
'fk_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();
649 public $stats_bom = array();
650 public $stats_mrptoconsume = array();
651 public $stats_mrptoproduce = array();
652 public $stats_facturerec = array();
653 public $stats_facture_fournisseur = array();
668 public $product_fourn_id;
674 public $product_id_already_linked;
685 public $stock_warehouse = array();
690 public $fk_default_warehouse;
695 public $fk_price_expression;
713 public $fourn_price_base_type;
730 public $ref_supplier;
744 public $price_autogen = 0;
751 public $supplierprices;
771 public $is_object_used;
782 public $is_sousproduit_qty;
794 public $is_sousproduit_incdec;
799 public $mandatory_period;
830 public $fields = array(
831 'rowid' => array(
'type' =>
'integer',
'label' =>
'TechnicalID',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'index' => 1,
'position' => 1,
'comment' =>
'Id'),
832 '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'),
833 'entity' => array(
'type' =>
'integer',
'label' =>
'Entity',
'enabled' => 1,
'visible' => 0,
'default' =>
'1',
'notnull' => 1,
'index' => 1,
'position' => 5),
834 'label' => array(
'type' =>
'varchar(255)',
'label' =>
'Label',
'enabled' => 1,
'visible' => 1,
'notnull' => 1,
'showoncombobox' => 2,
'position' => 15,
'csslist' =>
'tdoverflowmax250'),
835 'barcode' => array(
'type' =>
'varchar(255)',
'label' =>
'Barcode',
'enabled' =>
'isModEnabled("barcode")',
'position' => 20,
'visible' => -1,
'showoncombobox' => 3,
'cssview' =>
'tdwordbreak',
'csslist' =>
'tdoverflowmax125'),
836 'fk_barcode_type' => array(
'type' =>
'integer',
'label' =>
'BarcodeType',
'enabled' => 1,
'position' => 21,
'notnull' => 0,
'visible' => -1,),
837 'note_public' => array(
'type' =>
'html',
'label' =>
'NotePublic',
'enabled' => 1,
'visible' => 0,
'position' => 61),
838 'note' => array(
'type' =>
'html',
'label' =>
'NotePrivate',
'enabled' => 1,
'visible' => 0,
'position' => 62),
839 'datec' => array(
'type' =>
'datetime',
'label' =>
'DateCreation',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 500),
840 'tms' => array(
'type' =>
'timestamp',
'label' =>
'DateModification',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 501),
842 'fk_user_author' => array(
'type' =>
'integer',
'label' =>
'UserAuthor',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 510,
'foreignkey' =>
'llx_user.rowid'),
843 'fk_user_modif' => array(
'type' =>
'integer',
'label' =>
'UserModif',
'enabled' => 1,
'visible' => -2,
'notnull' => -1,
'position' => 511),
845 'localtax1_tx' => array(
'type' =>
'double(6,3)',
'label' =>
'Localtax1tx',
'enabled' => 1,
'position' => 150,
'notnull' => 0,
'visible' => -1,),
846 'localtax1_type' => array(
'type' =>
'varchar(10)',
'label' =>
'Localtax1type',
'enabled' => 1,
'position' => 155,
'notnull' => 1,
'visible' => -1,),
847 'localtax2_tx' => array(
'type' =>
'double(6,3)',
'label' =>
'Localtax2tx',
'enabled' => 1,
'position' => 160,
'notnull' => 0,
'visible' => -1,),
848 'localtax2_type' => array(
'type' =>
'varchar(10)',
'label' =>
'Localtax2type',
'enabled' => 1,
'position' => 165,
'notnull' => 1,
'visible' => -1,),
849 'last_main_doc' => array(
'type' =>
'varchar(255)',
'label' =>
'LastMainDoc',
'enabled' => 1,
'visible' => -1,
'position' => 170),
850 'import_key' => array(
'type' =>
'varchar(14)',
'label' =>
'ImportId',
'enabled' => 1,
'visible' => -2,
'notnull' => -1,
'index' => 0,
'position' => 1000),
853 'mandatory_period' => array(
'type' =>
'integer',
'label' =>
'mandatoryperiod',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'default' =>
'0',
'index' => 1,
'position' => 1000),
874 $this->ismultientitymanaged = 1;
875 $this->isextrafieldmanaged = 1;
888 $this->
ref = trim($this->
ref);
916 public function create($user, $notrigger = 0)
918 global
$conf, $langs;
924 $this->
ref = trim($this->
ref);
928 $this->label = trim($this->label);
929 $this->price_ttc = (float)
price2num($this->price_ttc);
931 $this->price_min_ttc = (float)
price2num($this->price_min_ttc);
932 $this->price_min = (float)
price2num($this->price_min);
933 $this->price_label = trim($this->price_label);
934 if (empty($this->tva_tx)) {
937 if (empty($this->tva_npr)) {
941 if (empty($this->localtax1_tx)) {
942 $this->localtax1_tx = 0;
944 if (empty($this->localtax2_tx)) {
945 $this->localtax2_tx = 0;
947 if (empty($this->localtax1_type)) {
948 $this->localtax1_type =
'0';
950 if (empty($this->localtax2_type)) {
951 $this->localtax2_type =
'0';
953 if (empty($this->
price)) {
956 if (empty($this->price_min)) {
957 $this->price_min = 0;
960 if (empty($this->price_by_qty)) {
961 $this->price_by_qty = 0;
964 if (empty($this->
status)) {
967 if (empty($this->status_buy)) {
968 $this->status_buy = 0;
977 if ($this->price_base_type ==
'TTC' && $this->price_ttc > 0) {
978 $price_ttc =
price2num($this->price_ttc,
'MU');
979 $price_ht =
price2num($this->price_ttc / (1 + ($this->tva_tx / 100)),
'MU');
983 if ($this->price_base_type !=
'TTC' && $this->
price > 0) {
985 $price_ttc =
price2num($this->
price * (1 + ($this->tva_tx / 100)),
'MU');
989 if (($this->price_min_ttc > 0) && ($this->price_base_type ==
'TTC')) {
990 $price_min_ttc =
price2num($this->price_min_ttc,
'MU');
991 $price_min_ht =
price2num($this->price_min_ttc / (1 + ($this->tva_tx / 100)),
'MU');
995 if (($this->price_min > 0) && ($this->price_base_type !=
'TTC')) {
996 $price_min_ht =
price2num($this->price_min,
'MU');
997 $price_min_ttc =
price2num($this->price_min * (1 + ($this->tva_tx / 100)),
'MU');
1000 $this->accountancy_code_buy = trim($this->accountancy_code_buy);
1001 $this->accountancy_code_buy_intra = trim($this->accountancy_code_buy_intra);
1002 $this->accountancy_code_buy_export = trim($this->accountancy_code_buy_export);
1003 $this->accountancy_code_sell = trim($this->accountancy_code_sell);
1004 $this->accountancy_code_sell_intra = trim($this->accountancy_code_sell_intra);
1005 $this->accountancy_code_sell_export = trim($this->accountancy_code_sell_export);
1008 $this->barcode = trim($this->barcode);
1009 $this->mandatory_period = empty($this->mandatory_period) ? 0 : $this->mandatory_period;
1011 if (empty($this->label)) {
1012 $this->error =
'ErrorMandatoryParametersNotProvided';
1016 if (empty($this->
ref) || $this->
ref ==
'auto') {
1018 $module =
getDolGlobalString(
'PRODUCT_CODEPRODUCT_ADDON',
'mod_codeproduct_leopard');
1019 if ($module !=
'mod_codeproduct_leopard') {
1020 if (substr($module, 0, 16) ==
'mod_codeproduct_' && substr($module, -3) ==
'php') {
1021 $module = substr($module, 0,
dol_strlen($module) - 4);
1024 $modCodeProduct =
new $module();
1025 '@phan-var-force ModeleProductCode $modCodeProduct';
1026 if (!empty($modCodeProduct->code_auto)) {
1027 $this->
ref = $modCodeProduct->getNextValue($this, $this->
type);
1029 unset($modCodeProduct);
1032 if (empty($this->
ref)) {
1033 $this->error =
'ProductModuleNotSetupForAutoRef';
1038 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);
1042 if (empty($this->date_creation)) {
1043 $this->date_creation = $now;
1049 if ($this->barcode ==
'-1' || $this->barcode ==
'auto') {
1050 $this->barcode = $this->
get_barcode($this, $this->barcode_type_code);
1055 $result = $this->
verify();
1058 $sql =
"SELECT count(*) as nb";
1059 $sql .=
" FROM ".$this->db->prefix().
"product";
1060 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
1061 $sql .=
" AND ref = '".$this->db->escape($this->
ref).
"'";
1063 $result = $this->db->query($sql);
1065 $obj = $this->db->fetch_object($result);
1066 if ($obj->nb == 0) {
1068 $sql =
"INSERT INTO ".$this->db->prefix().
"product (";
1072 $sql .=
", ref_ext";
1073 $sql .=
", price_min";
1074 $sql .=
", price_min_ttc";
1076 $sql .=
", fk_user_author";
1077 $sql .=
", fk_product_type";
1079 $sql .=
", price_ttc";
1080 $sql .=
", price_base_type";
1081 $sql .=
", price_label";
1085 $sql .=
", accountancy_code_buy";
1086 $sql .=
", accountancy_code_buy_intra";
1087 $sql .=
", accountancy_code_buy_export";
1088 $sql .=
", accountancy_code_sell";
1089 $sql .=
", accountancy_code_sell_intra";
1090 $sql .=
", accountancy_code_sell_export";
1093 $sql .=
", finished";
1094 $sql .=
", tobatch";
1095 $sql .=
", sell_or_eat_by_mandatory";
1096 $sql .=
", batch_mask";
1097 $sql .=
", fk_unit";
1098 $sql .=
", mandatory_period";
1099 $sql .=
") VALUES (";
1100 $sql .=
"'".$this->db->idate($this->date_creation).
"'";
1101 $sql .=
", ".(!empty($this->entity) ? (int) $this->entity : (int)
$conf->entity);
1102 $sql .=
", '".$this->db->escape($this->
ref).
"'";
1103 $sql .=
", ".(!empty($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
1104 $sql .=
", ".price2num($price_min_ht);
1105 $sql .=
", ".price2num($price_min_ttc);
1106 $sql .=
", ".(!empty($this->label) ?
"'".$this->db->escape($this->label).
"'" :
"null");
1107 $sql .=
", ".((int) $user->id);
1108 $sql .=
", ".((int) $this->
type);
1109 $sql .=
", ".price2num($price_ht,
'MT');
1110 $sql .=
", ".price2num($price_ttc,
'MT');
1111 $sql .=
", '".$this->db->escape($this->price_base_type).
"'";
1112 $sql .=
", ".(!empty($this->price_label) ?
"'".$this->db->escape($this->price_label).
"'" :
"null");
1113 $sql .=
", ".((int) $this->
status);
1114 $sql .=
", ".((int) $this->status_buy);
1116 $sql .=
", '".$this->db->escape($this->accountancy_code_buy).
"'";
1117 $sql .=
", '".$this->db->escape($this->accountancy_code_buy_intra).
"'";
1118 $sql .=
", '".$this->db->escape($this->accountancy_code_buy_export).
"'";
1119 $sql .=
", '".$this->db->escape($this->accountancy_code_sell).
"'";
1120 $sql .=
", '".$this->db->escape($this->accountancy_code_sell_intra).
"'";
1121 $sql .=
", '".$this->db->escape($this->accountancy_code_sell_export).
"'";
1123 $sql .=
", '".$this->db->escape($this->canvas).
"'";
1124 $sql .=
", ".((!isset($this->finished) || $this->finished < 0 || $this->finished ==
'') ?
'NULL' : (int) $this->finished);
1125 $sql .=
", ".((empty($this->status_batch) || $this->status_batch < 0) ?
'0' : ((int) $this->status_batch));
1126 $sql .=
", ".((empty($this->sell_or_eat_by_mandatory) || $this->sell_or_eat_by_mandatory < 0) ? 0 : ((int) $this->sell_or_eat_by_mandatory));
1127 $sql .=
", '".$this->db->escape($this->batch_mask).
"'";
1128 $sql .=
", ".($this->fk_unit > 0 ? ((int) $this->fk_unit) :
'NULL');
1129 $sql .=
", '".$this->db->escape($this->mandatory_period).
"'";
1132 dol_syslog(get_class($this).
"::Create", LOG_DEBUG);
1134 $result = $this->db->query($sql);
1136 $id = $this->db->last_insert_id($this->db->prefix().
"product");
1140 $this->
price = $price_ht;
1141 $this->price_ttc = $price_ttc;
1142 $this->price_min = $price_min_ht;
1143 $this->price_min_ttc = $price_min_ttc;
1147 if ($this->
update($id, $user, 1,
'add') <= 0) {
1152 $this->error = $this->db->lasterror();
1157 $this->db->query(
"DELETE FROM " . $this->db->prefix() .
"product_perentity WHERE fk_product = " .((int) $this->id) .
" AND entity = " . ((
int)
$conf->entity));
1159 $sql =
"INSERT INTO " . $this->db->prefix() .
"product_perentity (";
1160 $sql .=
" fk_product";
1162 $sql .=
", accountancy_code_buy";
1163 $sql .=
", accountancy_code_buy_intra";
1164 $sql .=
", accountancy_code_buy_export";
1165 $sql .=
", accountancy_code_sell";
1166 $sql .=
", accountancy_code_sell_intra";
1167 $sql .=
", accountancy_code_sell_export";
1168 $sql .=
") VALUES (";
1170 $sql .=
", " . ((int)
$conf->entity);
1171 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy) .
"'";
1172 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_intra) .
"'";
1173 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_export) .
"'";
1174 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell) .
"'";
1175 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_intra) .
"'";
1176 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_export) .
"'";
1178 $result = $this->db->query($sql);
1181 $this->error =
'ErrorFailedToInsertAccountancyForEntity';
1186 $this->error =
'ErrorFailedToGetInsertedId';
1190 $this->error = $this->db->lasterror();
1194 $langs->load(
"products");
1196 $this->error =
"ErrorProductAlreadyExists";
1197 dol_syslog(get_class($this).
"::Create fails, ref ".$this->
ref.
" already exists");
1201 $this->error = $this->db->lasterror();
1204 if (!$error && !$notrigger) {
1206 $result = $this->
call_trigger(
'PRODUCT_CREATE', $user);
1214 $this->db->commit();
1217 $this->db->rollback();
1221 $this->db->rollback();
1222 dol_syslog(get_class($this).
"::Create fails verify ".implode(
',', $this->errors), LOG_WARNING);
1238 $this->errors = array();
1241 $this->
ref = trim($this->
ref);
1244 $this->errors[] =
'ErrorBadRef';
1248 $arrayofnonnegativevalue = array(
'weight' =>
'Weight',
'width' =>
'Width',
'height' =>
'Height',
'length' =>
'Length',
'surface' =>
'Surface',
'volume' =>
'Volume');
1249 foreach ($arrayofnonnegativevalue as $key => $value) {
1250 if (property_exists($this, $key) && !empty($this->$key) && ($this->$key < 0)) {
1251 $langs->loadLangs(array(
"main",
"other"));
1252 $this->error = $langs->trans(
"FieldCannotBeNegative", $langs->transnoentitiesnoconv($value));
1253 $this->errors[] = $this->error;
1258 $rescode = $this->
check_barcode($this->barcode, $this->barcode_type_code);
1260 if ($rescode == -1) {
1261 $this->errors[] =
'ErrorBadBarCodeSyntax';
1262 } elseif ($rescode == -2) {
1263 $this->errors[] =
'ErrorBarCodeRequired';
1264 } elseif ($rescode == -3) {
1266 $this->errors[] =
'ErrorBarCodeAlreadyUsed';
1294 $dirsociete = array_merge(array(
'/core/modules/barcode/'),
$conf->modules_parts[
'barcode']);
1295 foreach ($dirsociete as $dirroot) {
1302 $mod =
new $module();
1303 '@phan-var-force ModeleNumRefBarCode $mod';
1305 dol_syslog(get_class($this).
"::check_barcode value=".$valuetotest.
" type=".$typefortest.
" module=".$module);
1306 $result = $mod->verif($this->db, $valuetotest, $this, 0, $typefortest);
1324 public function update($id, $user, $notrigger = 0, $action =
'update', $updatetype =
false)
1326 global $langs,
$conf, $hookmanager;
1331 if (!$this->label) {
1332 $this->label =
'MISSING LABEL';
1337 $this->
ref = trim($this->
ref);
1341 $this->label = trim($this->label);
1343 $this->note_private = (isset($this->note_private) ? trim($this->note_private) :
null);
1344 $this->note_public = (isset($this->note_public) ? trim($this->note_public) :
null);
1345 $this->net_measure =
price2num($this->net_measure);
1346 $this->net_measure_units = (empty($this->net_measure_units) ?
'' : trim((
string) $this->net_measure_units));
1347 $this->weight =
price2num($this->weight);
1348 $this->weight_units = (empty($this->weight_units) ?
'' : trim((
string) $this->weight_units));
1349 $this->length =
price2num($this->length);
1350 $this->length_units = (empty($this->length_units) ?
'' : trim((
string) $this->length_units));
1352 $this->width_units = (empty($this->width_units) ?
'' : trim((
string) $this->width_units));
1353 $this->height =
price2num($this->height);
1354 $this->height_units = (empty($this->height_units) ?
'' : trim((
string) $this->height_units));
1355 $this->surface =
price2num($this->surface);
1356 $this->surface_units = (empty($this->surface_units) ?
'' : trim((
string) $this->surface_units));
1357 $this->volume =
price2num($this->volume);
1358 $this->volume_units = (empty($this->volume_units) ?
'' : trim((
string) $this->volume_units));
1361 if (is_numeric($this->length_units)) {
1362 $this->width_units = $this->length_units;
1364 if (is_numeric($this->length_units)) {
1365 $this->height_units = $this->length_units;
1369 if (empty($this->surface) && !empty($this->length) && !empty($this->width) && $this->length_units == $this->width_units) {
1370 $this->surface = (float) $this->length * (
float) $this->width;
1373 if (empty($this->volume) && !empty($this->surface) && !empty($this->height) && $this->length_units == $this->height_units) {
1374 $this->volume = $this->surface * (float) $this->height;
1378 if (empty($this->tva_tx)) {
1381 if (empty($this->tva_npr)) {
1384 if (empty($this->localtax1_tx)) {
1385 $this->localtax1_tx = 0;
1387 if (empty($this->localtax2_tx)) {
1388 $this->localtax2_tx = 0;
1390 if (empty($this->localtax1_type)) {
1391 $this->localtax1_type =
'0';
1393 if (empty($this->localtax2_type)) {
1394 $this->localtax2_type =
'0';
1396 if (empty($this->
status)) {
1399 if (empty($this->status_buy)) {
1400 $this->status_buy = 0;
1403 if (empty($this->country_id)) {
1404 $this->country_id = 0;
1407 if (empty($this->state_id)) {
1408 $this->state_id = 0;
1412 $this->barcode = (empty($this->barcode) ?
'' : trim($this->barcode));
1414 $this->accountancy_code_buy = trim($this->accountancy_code_buy);
1415 $this->accountancy_code_buy_intra = (!empty($this->accountancy_code_buy_intra) ? trim($this->accountancy_code_buy_intra) :
'');
1416 $this->accountancy_code_buy_export = trim($this->accountancy_code_buy_export);
1417 $this->accountancy_code_sell = trim($this->accountancy_code_sell);
1418 $this->accountancy_code_sell_intra = trim($this->accountancy_code_sell_intra);
1419 $this->accountancy_code_sell_export = trim($this->accountancy_code_sell_export);
1426 if ($action !=
'add') {
1427 $result = $this->
verify();
1435 if (is_null($this->oldcopy) || (is_object($this->oldcopy) && $this->oldcopy->isEmpty())) {
1440 if ($this->
hasbatch() && !$this->oldcopy->hasbatch()) {
1442 $valueforundefinedlot =
'000000';
1447 dol_syslog(
"Flag batch of product id=".$this->
id.
" is set to ON, so we will create missing records into product_batch");
1450 foreach ($this->stock_warehouse as $idW => $ObjW) {
1452 foreach ($ObjW->detail_batch as $detail) {
1453 if ($detail->batch == $valueforundefinedlot || $detail->batch ==
'Undefined') {
1455 $sqlclean =
"DELETE FROM ".$this->db->prefix().
"product_batch WHERE batch in('Undefined', '".$this->db->escape($valueforundefinedlot).
"') AND fk_product_stock = ".((int) $ObjW->id);
1456 $result = $this->db->query($sqlclean);
1464 $qty_batch += $detail->qty;
1468 if ($ObjW->real != $qty_batch) {
1470 $ObjBatch->batch = $valueforundefinedlot;
1471 $ObjBatch->qty = ($ObjW->real - $qty_batch);
1472 $ObjBatch->fk_product_stock = (int) $ObjW->id;
1474 if ($ObjBatch->create($user, 1) < 0) {
1476 $this->errors = $ObjBatch->errors;
1481 if ($ObjLot->fetch(0, $this->id, $valueforundefinedlot) == 0) {
1482 $ObjLot->fk_product = $this->id;
1483 $ObjLot->entity = $this->entity;
1484 $ObjLot->fk_user_creat = $user->id;
1485 $ObjLot->batch = $valueforundefinedlot;
1486 if ($ObjLot->create($user,
true) < 0) {
1488 $this->errors = $ObjLot->errors;
1497 if ($this->barcode == -1) {
1498 $this->barcode = $this->
get_barcode($this, $this->barcode_type_code);
1501 $sql =
"UPDATE ".$this->db->prefix().
"product";
1502 $sql .=
" SET label = '".$this->db->escape($this->label).
"'";
1505 $sql .=
", fk_product_type = ".((int) $this->
type);
1508 $sql .=
", ref = '".$this->db->escape($this->
ref).
"'";
1509 $sql .=
", ref_ext = ".(!empty($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
1510 $sql .=
", default_vat_code = ".($this->default_vat_code ?
"'".$this->db->escape($this->default_vat_code).
"'" :
"null");
1511 $sql .=
", tva_tx = ".((float) $this->tva_tx);
1512 $sql .=
", recuperableonly = ".((int) $this->tva_npr);
1513 $sql .=
", localtax1_tx = ".((float) $this->localtax1_tx);
1514 $sql .=
", localtax2_tx = ".((float) $this->localtax2_tx);
1515 $sql .=
", localtax1_type = ".($this->localtax1_type !=
'' ?
"'".$this->db->escape($this->localtax1_type).
"'" :
"'0'");
1516 $sql .=
", localtax2_type = ".($this->localtax2_type !=
'' ?
"'".$this->db->escape($this->localtax2_type).
"'" :
"'0'");
1518 $sql .=
", barcode = ".(empty($this->barcode) ?
"null" :
"'".$this->db->escape($this->barcode).
"'");
1519 $sql .=
", fk_barcode_type = ".(empty($this->barcode_type) ?
"null" : $this->db->escape($this->barcode_type));
1521 $sql .=
", tosell = ".(int) $this->
status;
1522 $sql .=
", tobuy = ".(int) $this->status_buy;
1523 $sql .=
", tobatch = ".((empty($this->status_batch) || $this->status_batch < 0) ?
'0' : (int) $this->status_batch);
1524 $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);
1525 $sql .=
", batch_mask = '".$this->db->escape($this->batch_mask).
"'";
1527 $sql .=
", finished = ".((!isset($this->finished) || $this->finished < 0 || $this->finished ==
'') ?
"null" : (int) $this->finished);
1528 $sql .=
", fk_default_bom = ".((!isset($this->fk_default_bom) || $this->fk_default_bom < 0 || $this->fk_default_bom ==
'') ?
"null" : (int) $this->fk_default_bom);
1529 $sql .=
", net_measure = ".($this->net_measure !=
'' ?
"'".$this->db->escape($this->net_measure).
"'" :
'null');
1530 $sql .=
", net_measure_units = ".($this->net_measure_units !=
'' ?
"'".$this->db->escape($this->net_measure_units).
"'" :
'null');
1531 $sql .=
", weight = ".($this->weight !=
'' ?
"'".$this->db->escape($this->weight).
"'" :
'null');
1532 $sql .=
", weight_units = ".($this->weight_units !=
'' ?
"'".$this->db->escape($this->weight_units).
"'" :
'null');
1533 $sql .=
", length = ".($this->length !=
'' ?
"'".$this->db->escape($this->length).
"'" :
'null');
1534 $sql .=
", length_units = ".($this->length_units !=
'' ?
"'".$this->db->escape($this->length_units).
"'" :
'null');
1535 $sql .=
", width= ".($this->width !=
'' ?
"'".$this->db->escape($this->width).
"'" :
'null');
1536 $sql .=
", width_units = ".($this->width_units !=
'' ?
"'".$this->db->escape($this->width_units).
"'" :
'null');
1537 $sql .=
", height = ".($this->height !=
'' ?
"'".$this->db->escape($this->height).
"'" :
'null');
1538 $sql .=
", height_units = ".($this->height_units !=
'' ?
"'".$this->db->escape($this->height_units).
"'" :
'null');
1539 $sql .=
", surface = ".($this->surface !=
'' ?
"'".$this->db->escape($this->surface).
"'" :
'null');
1540 $sql .=
", surface_units = ".($this->surface_units !=
'' ?
"'".$this->db->escape($this->surface_units).
"'" :
'null');
1541 $sql .=
", volume = ".($this->volume !=
'' ?
"'".$this->db->escape($this->volume).
"'" :
'null');
1542 $sql .=
", volume_units = ".($this->volume_units !=
'' ?
"'".$this->db->escape($this->volume_units).
"'" :
'null');
1543 $sql .=
", fk_default_warehouse = ".($this->fk_default_warehouse > 0 ? ((int) $this->fk_default_warehouse) :
'null');
1544 $sql .=
", fk_default_workstation = ".($this->fk_default_workstation > 0 ? ((int) $this->fk_default_workstation) :
'null');
1545 $sql .=
", seuil_stock_alerte = ".((isset($this->seuil_stock_alerte) && is_numeric($this->seuil_stock_alerte)) ? (
float) $this->seuil_stock_alerte :
'null');
1546 $sql .=
", description = '".$this->db->escape($this->
description).
"'";
1547 $sql .=
", url = ".($this->url ?
"'".$this->db->escape($this->url).
"'" :
'null');
1548 $sql .=
", customcode = '".$this->db->escape($this->customcode).
"'";
1549 $sql .=
", fk_country = ".($this->country_id > 0 ? (int) $this->country_id :
'null');
1550 $sql .=
", fk_state = ".($this->state_id > 0 ? (int) $this->state_id :
'null');
1551 $sql .=
", lifetime = ".($this->lifetime > 0 ? (int) $this->lifetime :
'null');
1552 $sql .=
", qc_frequency = ".($this->qc_frequency > 0 ? (int) $this->qc_frequency :
'null');
1553 $sql .=
", note = ".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
'null');
1554 $sql .=
", note_public = ".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
'null');
1555 $sql .=
", duration = '".$this->db->escape($this->duration_value.$this->duration_unit).
"'";
1557 $sql .=
", accountancy_code_buy = '" . $this->db->escape($this->accountancy_code_buy) .
"'";
1558 $sql .=
", accountancy_code_buy_intra = '" . $this->db->escape($this->accountancy_code_buy_intra) .
"'";
1559 $sql .=
", accountancy_code_buy_export = '" . $this->db->escape($this->accountancy_code_buy_export) .
"'";
1560 $sql .=
", accountancy_code_sell= '" . $this->db->escape($this->accountancy_code_sell) .
"'";
1561 $sql .=
", accountancy_code_sell_intra= '" . $this->db->escape($this->accountancy_code_sell_intra) .
"'";
1562 $sql .=
", accountancy_code_sell_export= '" . $this->db->escape($this->accountancy_code_sell_export) .
"'";
1564 $sql .=
", desiredstock = ".((isset($this->desiredstock) && is_numeric($this->desiredstock)) ? (
float) $this->desiredstock :
"null");
1565 $sql .=
", cost_price = ".($this->cost_price !=
'' ? $this->db->escape($this->cost_price) :
'null');
1566 $sql .=
", fk_unit= ".(!$this->fk_unit ?
'NULL' : (int) $this->fk_unit);
1567 $sql .=
", price_autogen = ".(!$this->price_autogen ? 0 : 1);
1568 $sql .=
", fk_price_expression = ".($this->fk_price_expression != 0 ? (int) $this->fk_price_expression :
'NULL');
1569 $sql .=
", fk_user_modif = ".($user->id > 0 ? $user->id :
'NULL');
1570 $sql .=
", mandatory_period = ".($this->mandatory_period);
1572 $sql .=
" WHERE rowid = ".((int) $id);
1574 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
1576 $resql = $this->db->query($sql);
1583 $this->db->rollback();
1592 $this->db->query(
"DELETE FROM " . $this->db->prefix() .
"product_perentity WHERE fk_product = " . ((
int) $this->id) .
" AND entity = " . ((
int)
$conf->entity));
1594 $sql =
"INSERT INTO " . $this->db->prefix() .
"product_perentity (";
1595 $sql .=
" fk_product";
1597 $sql .=
", accountancy_code_buy";
1598 $sql .=
", accountancy_code_buy_intra";
1599 $sql .=
", accountancy_code_buy_export";
1600 $sql .=
", accountancy_code_sell";
1601 $sql .=
", accountancy_code_sell_intra";
1602 $sql .=
", accountancy_code_sell_export";
1603 $sql .=
") VALUES (";
1604 $sql .= ((int) $this->
id);
1605 $sql .=
", " . ((int)
$conf->entity);
1606 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy) .
"'";
1607 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_intra) .
"'";
1608 $sql .=
", '" . $this->db->escape($this->accountancy_code_buy_export) .
"'";
1609 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell) .
"'";
1610 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_intra) .
"'";
1611 $sql .=
", '" . $this->db->escape($this->accountancy_code_sell_export) .
"'";
1613 $result = $this->db->query($sql);
1616 $this->error =
'ErrorFailedToUpdateAccountancyForEntity';
1620 if (!$this->
hasbatch() && $this->oldcopy->hasbatch()) {
1622 $sql =
'SELECT pb.qty, ps.fk_entrepot, pb.batch FROM '.MAIN_DB_PREFIX.
'product_batch as pb';
1623 $sql .=
' INNER JOIN '.MAIN_DB_PREFIX.
'product_stock as ps ON (ps.rowid = pb.fk_product_stock)';
1624 $sql .=
' WHERE ps.fk_product = '.(int) $this->
id;
1626 $resql = $this->db->query($sql);
1630 while ($obj = $this->db->fetch_object($resql)) {
1632 $fk_entrepot = $obj->fk_entrepot;
1636 $batch = $obj->batch;
1639 $addOremove = $value > 0 ? 1 : 0;
1640 $label = $langs->trans(
'BatchStockMouvementAddInGlobal');
1641 $res = $this->
correct_stock_batch($user, $fk_entrepot, abs($value), $addOremove, $label, $price, $dlc, $dluo, $batch, $inventorycode,
'',
null, 0,
null,
true);
1644 $label = $langs->trans(
'BatchStockMouvementAddInGlobal');
1645 $res = $this->
correct_stock($user, $fk_entrepot, abs($value), (
int) empty($addOremove), $label, $price, $inventorycode,
'',
null, 0);
1664 if (!$error && !$notrigger) {
1666 $result = $this->
call_trigger(
'PRODUCT_MODIFY', $user);
1673 if (!$error && (is_object($this->oldcopy) && $this->oldcopy->ref !== $this->ref)) {
1675 if (
$conf->product->dir_output) {
1678 if (file_exists($olddir)) {
1682 $res = @rename($olddir, $newdir);
1684 $langs->load(
"errors");
1685 $this->error = $langs->trans(
'ErrorFailToRenameDir', $olddir, $newdir);
1689 require_once DOL_DOCUMENT_ROOT .
'/ecm/class/ecmfiles.class.php';
1690 $ecmfiles =
new EcmFiles($this->db);
1691 $ecmfiles->updateAfterRename(
"produit/".
dol_sanitizeFileName($this->oldcopy->ref),
"produit/".dol_sanitizeFileName($this->ref));
1698 if (isModEnabled(
'variants')) {
1699 include_once DOL_DOCUMENT_ROOT.
'/variants/class/ProductCombination.class.php';
1703 foreach ($comb->fetchAllByFkProductParent($this->id) as $currcomb) {
1704 $currcomb->updateProperties($this, $user);
1708 $this->db->commit();
1711 $this->db->rollback();
1715 if ($this->db->errno() ==
'DB_ERROR_RECORD_ALREADY_EXISTS') {
1716 $langs->load(
"errors");
1717 if (empty(
$conf->barcode->enabled) || empty($this->barcode)) {
1718 $this->error = $langs->trans(
"Error").
" : ".$langs->trans(
"ErrorProductAlreadyExists", $this->
ref);
1720 $this->error = $langs->trans(
"Error").
" : ".$langs->trans(
"ErrorProductBarCodeAlreadyExists", $this->barcode);
1722 $this->errors[] = $this->error;
1723 $this->db->rollback();
1726 $this->error = $langs->trans(
"Error").
" : ".$this->db->error().
" - ".$sql;
1727 $this->errors[] = $this->error;
1728 $this->db->rollback();
1733 $this->db->rollback();
1734 dol_syslog(get_class($this).
"::Update fails verify ".implode(
',', $this->errors), LOG_WARNING);
1746 public function delete(
User $user, $notrigger = 0)
1749 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1754 if (empty($this->
id)) {
1755 $this->error =
"Object must be fetched before calling delete";
1758 if (($this->
isProduct() && !$user->
hasRight(
'produit',
'supprimer')) || ($this->isService() && !$user->hasRight(
'service',
'supprimer'))) {
1759 $this->error =
"ErrorForbidden";
1764 if (empty($objectisused)) {
1767 if (!$error && empty($notrigger)) {
1769 $result = $this->
call_trigger(
'PRODUCT_DELETE', $user);
1778 $sql =
"DELETE FROM ".$this->db->prefix().
'product_batch';
1779 $sql .=
" WHERE fk_product_stock IN (";
1780 $sql .=
"SELECT rowid FROM ".$this->db->prefix().
'product_stock';
1781 $sql .=
" WHERE fk_product = ".((int) $this->
id).
")";
1783 $result = $this->db->query($sql);
1786 $this->errors[] = $this->db->lasterror();
1792 $elements = array(
'product_fournisseur_price',
'product_price',
'product_lang',
'categorie_product',
'product_stock',
'product_customer_price',
'product_lot');
1793 foreach ($elements as $table) {
1795 $sql =
"DELETE FROM ".$this->db->prefix().$table;
1796 $sql .=
" WHERE fk_product = ".(int) $this->
id;
1798 $result = $this->db->query($sql);
1801 $this->errors[] = $this->db->lasterror();
1808 include_once DOL_DOCUMENT_ROOT.
'/variants/class/ProductCombination.class.php';
1809 include_once DOL_DOCUMENT_ROOT.
'/variants/class/ProductCombination2ValuePair.class.php';
1814 if ($prodcomb->deleteByFkProductParent($user, $this->id) < 0) {
1816 $this->errors[] =
'Error deleting combinations';
1820 if (!$error && ($prodcomb->fetchByFkProductChild($this->id) > 0) && ($prodcomb->delete($user) < 0)) {
1822 $this->errors[] =
'Error deleting child combination';
1828 $sql =
"DELETE FROM ".$this->db->prefix().
"product_association";
1829 $sql .=
" WHERE fk_product_pere = ".(int) $this->
id.
" OR fk_product_fils = ".(
int) $this->id;
1831 $result = $this->db->query($sql);
1834 $this->errors[] = $this->db->lasterror();
1843 dol_syslog(get_class($this).
"::delete error -4 ".$this->error, LOG_ERR);
1849 $sqlz =
"DELETE FROM ".$this->db->prefix().
"product";
1850 $sqlz .=
" WHERE rowid = ".(int) $this->
id;
1852 $resultz = $this->db->query($sqlz);
1855 $this->errors[] = $this->db->lasterror();
1871 if ($conf->product->dir_output) {
1872 $dir =
$conf->product->dir_output.
"/".$ref;
1873 if (file_exists($dir)) {
1876 $this->errors[] =
'ErrorFailToDeleteDir';
1884 $this->db->commit();
1887 foreach ($this->errors as $errmsg) {
1888 dol_syslog(get_class($this).
"::delete ".$errmsg, LOG_ERR);
1889 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1891 $this->db->rollback();
1895 $this->error =
"ErrorRecordIsUsedCantDelete";
1909 $sellByLabel = $langs->trans(
'SellByDate');
1910 $eatByLabel = $langs->trans(
'EatByDate');
1912 self::SELL_OR_EAT_BY_MANDATORY_ID_NONE => $langs->trans(
'BatchSellOrEatByMandatoryNone'),
1913 self::SELL_OR_EAT_BY_MANDATORY_ID_SELL_BY => $sellByLabel,
1914 self::SELL_OR_EAT_BY_MANDATORY_ID_EAT_BY => $eatByLabel,
1915 self::SELL_OR_EAT_BY_MANDATORY_ID_SELL_AND_EAT => $langs->trans(
'BatchSellOrEatByMandatoryAll', $sellByLabel, $eatByLabel),
1926 $sellOrEatByMandatoryLabel =
'';
1929 if (isset($sellOrEatByMandatoryList[$this->sell_or_eat_by_mandatory])) {
1930 $sellOrEatByMandatoryLabel = $sellOrEatByMandatoryList[$this->sell_or_eat_by_mandatory];
1933 return $sellOrEatByMandatoryLabel;
1946 $langs_available = $langs->get_available_languages(DOL_DOCUMENT_ROOT, 0, 2);
1947 $current_lang = $langs->getDefaultLang();
1949 foreach ($langs_available as $key => $value) {
1950 if ($key == $current_lang) {
1951 $sql =
"SELECT rowid";
1952 $sql .=
" FROM ".$this->db->prefix().
"product_lang";
1953 $sql .=
" WHERE fk_product = ".((int) $this->
id);
1954 $sql .=
" AND lang = '".$this->db->escape($key).
"'";
1956 $result = $this->db->query($sql);
1958 if ($this->db->num_rows($result)) {
1959 $sql2 =
"UPDATE ".$this->db->prefix().
"product_lang";
1961 $sql2 .=
" label='".$this->db->escape($this->label).
"',";
1962 $sql2 .=
" description='".$this->db->escape($this->
description).
"'";
1964 $sql2 .=
", note='".$this->db->escape($this->other).
"'";
1966 $sql2 .=
" WHERE fk_product = ".((int) $this->
id).
" AND lang = '".$this->db->escape($key).
"'";
1968 $sql2 =
"INSERT INTO ".$this->db->prefix().
"product_lang (fk_product, lang, label, description";
1973 $sql2 .=
" VALUES(".((int) $this->
id).
",'".$this->db->escape($key).
"','".$this->db->escape($this->label).
"',";
1974 $sql2 .=
" '".$this->db->escape($this->
description).
"'";
1976 $sql2 .=
", '".$this->db->escape($this->other).
"'";
1980 dol_syslog(get_class($this).
'::setMultiLangs key = current_lang = '.$key);
1981 if (!$this->db->query($sql2)) {
1982 $this->error = $this->db->lasterror();
1985 } elseif (isset($this->multilangs[$key])) {
1986 if (empty($this->multilangs[$key][
"label"])) {
1987 $this->errors[] = $key .
' : ' . $langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv(
"Label"));
1991 $sql =
"SELECT rowid";
1992 $sql .=
" FROM ".$this->db->prefix().
"product_lang";
1993 $sql .=
" WHERE fk_product = ".((int) $this->
id);
1994 $sql .=
" AND lang = '".$this->db->escape($key).
"'";
1996 $result = $this->db->query($sql);
1998 if ($this->db->num_rows($result)) {
1999 $sql2 =
"UPDATE ".$this->db->prefix().
"product_lang";
2001 $sql2 .=
" label = '".$this->db->escape($this->multilangs[
"$key"][
"label"]).
"',";
2002 $sql2 .=
" description = '".$this->db->escape($this->multilangs[
"$key"][
"description"]).
"'";
2005 $sql2 .=
", note = '".$this->db->escape($this->multilangs[
"$key"][
"other"]).
"'";
2007 $sql2 .=
" WHERE fk_product = ".((int) $this->
id).
" AND lang = '".$this->db->escape($key).
"'";
2009 $sql2 =
"INSERT INTO ".$this->db->prefix().
"product_lang (fk_product, lang, label, description";
2014 $sql2 .=
" VALUES(".((int) $this->
id).
",'".$this->db->escape($key).
"','".$this->db->escape($this->multilangs[
"$key"][
"label"]).
"',";
2015 $sql2 .=
" '".$this->db->escape($this->multilangs[
"$key"][
"description"]).
"'";
2018 $sql2 .=
", '".$this->db->escape($this->multilangs[
"$key"][
"other"]).
"'";
2024 if ($this->multilangs[
"$key"][
"label"] || $this->multilangs[
"$key"][
"description"]) {
2025 if (!$this->db->query($sql2)) {
2026 $this->error = $this->db->lasterror();
2036 $result = $this->
call_trigger(
'PRODUCT_SET_MULTILANGS', $user);
2038 $this->error = $this->db->lasterror();
2056 $sql =
"DELETE FROM ".$this->db->prefix().
"product_lang";
2057 $sql .=
" WHERE fk_product = ".((int) $this->
id).
" AND lang = '".$this->db->escape($langtodelete).
"'";
2059 dol_syslog(get_class($this).
'::delMultiLangs', LOG_DEBUG);
2060 $result = $this->db->query($sql);
2063 $result = $this->
call_trigger(
'PRODUCT_DEL_MULTILANGS', $user);
2065 $this->error = $this->db->lasterror();
2066 dol_syslog(get_class($this).
'::delMultiLangs error='.$this->error, LOG_ERR);
2072 $this->error = $this->db->lasterror();
2073 dol_syslog(get_class($this).
'::delMultiLangs error='.$this->error, LOG_ERR);
2094 if ($type ==
'buy') {
2095 $field =
'accountancy_code_buy';
2096 } elseif ($type ==
'buy_intra') {
2097 $field =
'accountancy_code_buy_intra';
2098 } elseif ($type ==
'buy_export') {
2099 $field =
'accountancy_code_buy_export';
2100 } elseif ($type ==
'sell') {
2101 $field =
'accountancy_code_sell';
2102 } elseif ($type ==
'sell_intra') {
2103 $field =
'accountancy_code_sell_intra';
2104 } elseif ($type ==
'sell_export') {
2105 $field =
'accountancy_code_sell_export';
2110 $sql =
"UPDATE ".$this->db->prefix().$this->table_element.
" SET ";
2111 $sql .=
"$field = '".$this->db->escape($value).
"'";
2112 $sql .=
" WHERE rowid = ".((int) $this->
id);
2115 $resql = $this->db->query($sql);
2119 $result = $this->
call_trigger(
'PRODUCT_MODIFY', $user);
2126 $this->db->rollback();
2130 $this->$field = $value;
2132 $this->db->commit();
2135 $this->error = $this->db->lasterror();
2136 $this->db->rollback();
2150 $current_lang = $langs->getDefaultLang();
2152 $sql =
"SELECT lang, label, description, note as other";
2153 $sql .=
" FROM ".$this->db->prefix().
"product_lang";
2154 $sql .=
" WHERE fk_product = ".((int) $this->
id);
2156 $result = $this->db->query($sql);
2158 while ($obj = $this->db->fetch_object($result)) {
2160 if ($obj->lang == $current_lang) {
2161 $this->label = $obj->label;
2163 $this->other = $obj->other;
2165 $this->multilangs[(string) $obj->lang][
"label"] = $obj->label;
2166 $this->multilangs[(string) $obj->lang][
"description"] = $obj->description;
2167 $this->multilangs[(string) $obj->lang][
"other"] = $obj->other;
2171 $this->error =
"Error: ".$this->db->lasterror().
" - ".$sql;
2184 $testExit = array(
'multiprices',
'multiprices_ttc',
'multiprices_base_type',
'multiprices_min',
'multiprices_min_ttc',
'multiprices_tva_tx',
'multiprices_recuperableonly');
2186 foreach ($testExit as $field) {
2187 if (!isset($this->$field)) {
2190 $tmparray = $this->$field;
2191 if (!isset($tmparray[$level])) {
2197 'level' => $level ? $level : 1,
2198 'multiprices' => (float) $this->multiprices[$level],
2199 'multiprices_ttc' => (
float) $this->multiprices_ttc[$level],
2200 'multiprices_base_type' => $this->multiprices_base_type[$level],
2201 'multiprices_min' => (float) $this->multiprices_min[$level],
2202 'multiprices_min_ttc' => (
float) $this->multiprices_min_ttc[$level],
2203 'multiprices_tva_tx' => (float) $this->multiprices_tva_tx[$level],
2204 'multiprices_recuperableonly' => (
float) $this->multiprices_recuperableonly[$level],
2227 if (empty($this->price_by_qty)) {
2228 $this->price_by_qty = 0;
2232 $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,";
2233 $sql .=
" localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, price_min,price_min_ttc,price_by_qty,entity,fk_price_expression) ";
2234 $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).
",";
2235 $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');
2238 dol_syslog(get_class($this).
"::_log_price", LOG_DEBUG);
2239 $resql = $this->db->query($sql);
2241 $this->error = $this->db->lasterror();
2261 $sql =
"DELETE FROM ".$this->db->prefix().
"product_price_by_qty";
2262 $sql .=
" WHERE fk_product_price = ".((int) $rowid);
2263 $resql = $this->db->query($sql);
2265 $sql =
"DELETE FROM ".$this->db->prefix().
"product_price";
2266 $sql .=
" WHERE rowid=".((int) $rowid);
2267 $resql = $this->db->query($sql);
2271 $this->error = $this->db->lasterror();
2286 public function getSellPrice($thirdparty_seller, $thirdparty_buyer, $pqp = 0)
2288 global $hookmanager, $action;
2291 if (is_object($hookmanager)) {
2292 $parameters = array(
'thirdparty_seller' => $thirdparty_seller,
'thirdparty_buyer' => $thirdparty_buyer,
'pqp' => $pqp);
2294 $reshook = $hookmanager->executeHooks(
'getSellPrice', $parameters, $this, $action);
2296 return $hookmanager->resArray;
2301 $tva_tx =
get_default_tva($thirdparty_seller, $thirdparty_buyer, $this->
id);
2302 $tva_npr =
get_default_npr($thirdparty_seller, $thirdparty_buyer, $this->
id);
2303 if (empty($tva_tx)) {
2307 $pu_ht = $this->price;
2308 $pu_ttc = $this->price_ttc;
2309 $price_min = $this->price_min;
2310 $price_base_type = $this->price_base_type;
2314 require_once DOL_DOCUMENT_ROOT.
'/product/class/productcustomerprice.class.php';
2318 $filter = array(
't.fk_product' => $this->
id,
't.fk_soc' => $thirdparty_buyer->id);
2321 $pricebycustomerexist =
false;
2322 $result = $prodcustprice->fetchAll(
'',
'', 0, 0, $filter);
2324 if (count($prodcustprice->lines) > 0) {
2325 $pricebycustomerexist =
true;
2326 $pu_ht =
price($prodcustprice->lines[0]->price);
2327 $price_min =
price($prodcustprice->lines[0]->price_min);
2328 $pu_ttc =
price($prodcustprice->lines[0]->price_ttc);
2329 $price_base_type = $prodcustprice->lines[0]->price_base_type;
2330 $tva_tx = $prodcustprice->lines[0]->tva_tx;
2331 if ($prodcustprice->lines[0]->default_vat_code && !preg_match(
'/\(.*\)/', $tva_tx)) {
2332 $tva_tx .=
' ('.$prodcustprice->lines[0]->default_vat_code.
')';
2334 $tva_npr = $prodcustprice->lines[0]->recuperableonly;
2335 if (empty($tva_tx)) {
2341 if (!$pricebycustomerexist && !empty($thirdparty_buyer->price_level)) {
2342 $pu_ht = $this->multiprices[$thirdparty_buyer->price_level];
2343 $pu_ttc = $this->multiprices_ttc[$thirdparty_buyer->price_level];
2344 $price_min = $this->multiprices_min[$thirdparty_buyer->price_level];
2345 $price_base_type = $this->multiprices_base_type[$thirdparty_buyer->price_level];
2348 if (isset($this->multiprices_tva_tx[$thirdparty_buyer->price_level])) {
2349 $tva_tx = $this->multiprices_tva_tx[$thirdparty_buyer->price_level];
2351 if (isset($this->multiprices_recuperableonly[$thirdparty_buyer->price_level])) {
2352 $tva_npr = $this->multiprices_recuperableonly[$thirdparty_buyer->price_level];
2354 if (empty($tva_tx)) {
2359 } elseif (
getDolGlobalString(
'PRODUIT_MULTIPRICES') && !empty($thirdparty_buyer->price_level)) {
2360 $pu_ht = $this->multiprices[$thirdparty_buyer->price_level];
2361 $pu_ttc = $this->multiprices_ttc[$thirdparty_buyer->price_level];
2362 $price_min = $this->multiprices_min[$thirdparty_buyer->price_level];
2363 $price_base_type = $this->multiprices_base_type[$thirdparty_buyer->price_level];
2365 if (isset($this->multiprices_tva_tx[$thirdparty_buyer->price_level])) {
2366 $tva_tx = $this->multiprices_tva_tx[$thirdparty_buyer->price_level];
2368 if (isset($this->multiprices_recuperableonly[$thirdparty_buyer->price_level])) {
2369 $tva_npr = $this->multiprices_recuperableonly[$thirdparty_buyer->price_level];
2371 if (empty($tva_tx)) {
2377 require_once DOL_DOCUMENT_ROOT.
'/product/class/productcustomerprice.class.php';
2381 $filter = array(
't.fk_product' => $this->
id,
't.fk_soc' => $thirdparty_buyer->id);
2383 $result = $prodcustprice->fetchAll(
'',
'', 0, 0, $filter);
2385 if (count($prodcustprice->lines) > 0) {
2386 $pu_ht =
price($prodcustprice->lines[0]->price);
2387 $price_min =
price($prodcustprice->lines[0]->price_min);
2388 $pu_ttc =
price($prodcustprice->lines[0]->price_ttc);
2389 $price_base_type = $prodcustprice->lines[0]->price_base_type;
2390 $tva_tx = $prodcustprice->lines[0]->tva_tx;
2391 if ($prodcustprice->lines[0]->default_vat_code && !preg_match(
'/\(.*\)/', $tva_tx)) {
2392 $tva_tx .=
' ('.$prodcustprice->lines[0]->default_vat_code.
')';
2394 $tva_npr = $prodcustprice->lines[0]->recuperableonly;
2395 if (empty($tva_tx)) {
2402 if ($this->prices_by_qty[0]) {
2405 foreach ($this->prices_by_qty_list[0] as $priceforthequantityarray) {
2406 if ($priceforthequantityarray[
'rowid'] != $pqp) {
2410 if ($priceforthequantityarray[
'price_base_type'] ==
'HT') {
2411 $pu_ht = $priceforthequantityarray[
'unitprice'];
2413 $pu_ttc = $priceforthequantityarray[
'unitprice'];
2420 if ($this->prices_by_qty[$thirdparty_buyer->price_level]) {
2423 foreach ($this->prices_by_qty_list[$thirdparty_buyer->price_level] as $priceforthequantityarray) {
2424 if ($priceforthequantityarray[
'rowid'] != $pqp) {
2428 if ($priceforthequantityarray[
'price_base_type'] ==
'HT') {
2429 $pu_ht = $priceforthequantityarray[
'unitprice'];
2431 $pu_ttc = $priceforthequantityarray[
'unitprice'];
2438 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);
2455 public function get_buyprice($prodfournprice, $qty, $product_id = 0, $fourn_ref =
'', $fk_soc = 0)
2458 global $action, $hookmanager;
2461 if (is_object($hookmanager)) {
2462 $parameters = array(
2463 'prodfournprice' => $prodfournprice,
2465 'product_id' => $product_id,
2466 'fourn_ref' => $fourn_ref,
2467 'fk_soc' => $fk_soc,
2470 $reshook = $hookmanager->executeHooks(
'getBuyPrice', $parameters, $this, $action);
2472 return $hookmanager->resArray;
2479 $sql =
"SELECT pfp.rowid, pfp.price as price, pfp.quantity as quantity, pfp.remise_percent, pfp.fk_soc,";
2480 $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,";
2481 $sql .=
" pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code,";
2482 $sql .=
" pfp.packaging";
2483 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price as pfp";
2484 $sql .=
" WHERE pfp.rowid = ".((int) $prodfournprice);
2486 $sql .=
" AND pfp.quantity <= ".((float) $qty);
2488 $sql .=
" ORDER BY pfp.quantity DESC";
2490 dol_syslog(get_class($this).
"::get_buyprice first search by prodfournprice/qty", LOG_DEBUG);
2491 $resql = $this->db->query($sql);
2493 $obj = $this->db->fetch_object($resql);
2494 if ($obj && $obj->quantity > 0) {
2495 if (isModEnabled(
'dynamicprices') && !empty($obj->fk_supplier_price_expression)) {
2497 $prod_supplier->product_fourn_price_id = $obj->rowid;
2498 $prod_supplier->id = $obj->fk_product;
2499 $prod_supplier->fourn_qty = $obj->quantity;
2500 $prod_supplier->fourn_tva_tx = $obj->tva_tx;
2501 $prod_supplier->fk_supplier_price_expression = $obj->fk_supplier_price_expression;
2503 include_once DOL_DOCUMENT_ROOT.
'/product/dynamic_price/class/price_parser.class.php';
2505 $price_result = $priceparser->parseProductSupplier($prod_supplier);
2506 if ($price_result >= 0) {
2507 $obj->price = $price_result;
2510 $this->product_fourn_price_id = $obj->rowid;
2511 $this->buyprice = $obj->price;
2512 $this->fourn_pu = $obj->price / $obj->quantity;
2513 $this->fourn_price_base_type =
'HT';
2514 $this->fourn_socid = $obj->fk_soc;
2515 $this->ref_fourn = $obj->ref_supplier;
2516 $this->ref_supplier = $obj->ref_supplier;
2517 $this->desc_supplier = $obj->desc_supplier;
2518 $this->remise_percent = $obj->remise_percent;
2519 $this->vatrate_supplier = $obj->tva_tx;
2520 $this->default_vat_code_supplier = $obj->default_vat_code;
2521 $this->fourn_multicurrency_price = $obj->multicurrency_price;
2522 $this->fourn_multicurrency_unitprice = $obj->multicurrency_unitprice;
2523 $this->fourn_multicurrency_tx = $obj->multicurrency_tx;
2524 $this->fourn_multicurrency_id = $obj->fk_multicurrency;
2525 $this->fourn_multicurrency_code = $obj->multicurrency_code;
2527 $this->packaging = $obj->packaging;
2529 $result = $obj->fk_product;
2533 $sql =
"SELECT pfp.rowid, pfp.price as price, pfp.quantity as quantity, pfp.remise_percent, pfp.fk_soc,";
2534 $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,";
2535 $sql .=
" pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code,";
2536 $sql .=
" pfp.packaging";
2537 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price as pfp";
2538 $sql .=
" WHERE 1 = 1";
2539 if ($product_id > 0) {
2540 $sql .=
" AND pfp.fk_product = ".((int) $product_id);
2542 if ($fourn_ref !=
'none') {
2543 $sql .=
" AND pfp.ref_fourn = '".$this->db->escape($fourn_ref).
"'";
2546 $sql .=
" AND pfp.fk_soc = ".((int) $fk_soc);
2549 $sql .=
" AND pfp.quantity <= ".((float) $qty);
2551 $sql .=
" ORDER BY pfp.quantity DESC";
2554 dol_syslog(get_class($this).
"::get_buyprice second search from qty/ref/product_id", LOG_DEBUG);
2555 $resql = $this->db->query($sql);
2557 $obj = $this->db->fetch_object($resql);
2558 if ($obj && $obj->quantity > 0) {
2559 if (isModEnabled(
'dynamicprices') && !empty($obj->fk_supplier_price_expression)) {
2561 $prod_supplier->product_fourn_price_id = $obj->rowid;
2562 $prod_supplier->id = $obj->fk_product;
2563 $prod_supplier->fourn_qty = $obj->quantity;
2564 $prod_supplier->fourn_tva_tx = $obj->tva_tx;
2565 $prod_supplier->fk_supplier_price_expression = $obj->fk_supplier_price_expression;
2567 include_once DOL_DOCUMENT_ROOT.
'/product/dynamic_price/class/price_parser.class.php';
2569 $price_result = $priceparser->parseProductSupplier($prod_supplier);
2571 $obj->price = $price_result;
2574 $this->product_fourn_price_id = $obj->rowid;
2575 $this->buyprice = $obj->price;
2576 $this->fourn_qty = $obj->quantity;
2577 $this->fourn_pu = $obj->price / $obj->quantity;
2578 $this->fourn_price_base_type =
'HT';
2579 $this->fourn_socid = $obj->fk_soc;
2580 $this->ref_fourn = $obj->ref_supplier;
2581 $this->ref_supplier = $obj->ref_supplier;
2582 $this->desc_supplier = $obj->desc_supplier;
2583 $this->remise_percent = $obj->remise_percent;
2584 $this->vatrate_supplier = $obj->tva_tx;
2585 $this->default_vat_code_supplier = $obj->default_vat_code;
2586 $this->fourn_multicurrency_price = $obj->multicurrency_price;
2587 $this->fourn_multicurrency_unitprice = $obj->multicurrency_unitprice;
2588 $this->fourn_multicurrency_tx = $obj->multicurrency_tx;
2589 $this->fourn_multicurrency_id = $obj->fk_multicurrency;
2590 $this->fourn_multicurrency_code = $obj->multicurrency_code;
2592 $this->packaging = $obj->packaging;
2594 $result = $obj->fk_product;
2600 $this->error = $this->db->lasterror();
2605 $this->error = $this->db->lasterror();
2629 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)
2635 dol_syslog(get_class($this).
"::update_price id=".$id.
" newprice=".$newprice.
" newpricebase=".$newpricebase.
" newminprice=".$newminprice.
" level=".$level.
" npr=".$newnpr.
" newdefaultvatcode=".$newdefaultvatcode);
2638 if (empty($this->tva_tx)) {
2639 $this->tva_tx = 0.0;
2641 if (empty($newnpr)) {
2644 if (empty($newminprice)) {
2649 if ($newvat ===
null || $newvat ==
'') {
2650 $newvat = (float) $this->tva_tx;
2653 $localtaxtype1 =
'';
2654 $localtaxtype2 =
'';
2659 return $this->
generateMultiprices($user, $newprice, $newpricebase, $newvat, $newnpr, $newpbq);
2662 if (!empty($newminprice) && ($newminprice > $newprice)) {
2663 $this->error =
'ErrorPriceCantBeLowerThanMinPrice';
2667 if ($newprice === 0 || $newprice !==
'') {
2668 if ($newpricebase ==
'TTC') {
2669 $price_ttc = (float)
price2num($newprice,
'MU');
2670 $price = (float)
price2num($newprice) / (1 + ((float) $newvat / 100));
2671 $price = (float)
price2num($price,
'MU');
2673 if ((
string) $newminprice !=
'0') {
2674 $price_min_ttc = (float)
price2num($newminprice,
'MU');
2675 $price_min = (float)
price2num($newminprice) / (1 + ($newvat / 100));
2676 $price_min = (float)
price2num($price_min,
'MU');
2679 $price_min_ttc = 0.0;
2682 $price = (float)
price2num($newprice,
'MU');
2683 $price_ttc = ($newnpr != 1) ? (
float)
price2num($newprice) * (1 + ($newvat / 100)) : $price;
2684 $price_ttc = (float)
price2num($price_ttc,
'MU');
2686 if ((
string) $newminprice !=
'0') {
2687 $price_min = (float)
price2num($newminprice,
'MU');
2688 $price_min_ttc = (float)
price2num($newminprice) * (1 + ($newvat / 100));
2689 $price_min_ttc = (float)
price2num($price_min_ttc,
'MU');
2693 $price_min_ttc = 0.0;
2697 if (count($localtaxes_array) > 0) {
2698 $localtaxtype1 = $localtaxes_array[
'0'];
2699 $localtax1 = $localtaxes_array[
'1'];
2700 $localtaxtype2 = $localtaxes_array[
'2'];
2701 $localtax2 = $localtaxes_array[
'3'];
2704 if (!empty($newdefaultvatcode)) {
2707 $sql =
"SELECT t.rowid, t.code, t.recuperableonly as tva_npr, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
2708 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_tva as t, ".MAIN_DB_PREFIX.
"c_country as c";
2709 $sql .=
" WHERE t.fk_pays = c.rowid AND c.code = '".$this->db->escape($mysoc->country_code).
"'";
2710 $sql .=
" AND t.taux = ".((float) $newdefaultvatcode).
" AND t.active = 1";
2711 $sql .=
" AND t.code = '".$this->db->escape($newdefaultvatcode).
"'";
2712 $resql = $this->db->query($sql);
2714 $obj = $this->db->fetch_object($resql);
2716 $npr = $obj->tva_npr;
2717 $localtax1 = $obj->localtax1;
2718 $localtax2 = $obj->localtax2;
2719 $localtaxtype1 = $obj->localtax1_type;
2720 $localtaxtype2 = $obj->localtax2_type;
2725 $localtaxtype1 =
'0';
2727 $localtaxtype2 =
'0';
2731 if (empty($localtax1)) {
2734 if (empty($localtax2)) {
2742 $sql =
"UPDATE ".$this->db->prefix().
"product SET";
2743 $sql .=
" price_base_type = '".$this->db->escape($newpricebase).
"',";
2744 $sql .=
" price = ".(float) $price.
",";
2745 $sql .=
" price_ttc = ".(float) $price_ttc.
",";
2746 $sql .=
" price_min = ".(float) $price_min.
",";
2747 $sql .=
" price_min_ttc = ".(float) $price_min_ttc.
",";
2748 $sql .=
" localtax1_tx = ".($localtax1 >= 0 ? (float) $localtax1 :
'NULL').
",";
2749 $sql .=
" localtax2_tx = ".($localtax2 >= 0 ? (float) $localtax2 :
'NULL').
",";
2750 $sql .=
" localtax1_type = ".($localtaxtype1 !=
'' ?
"'".$this->db->escape($localtaxtype1).
"'" :
"'0'").
",";
2751 $sql .=
" localtax2_type = ".($localtaxtype2 !=
'' ?
"'".$this->db->escape($localtaxtype2).
"'" :
"'0'").
",";
2752 $sql .=
" default_vat_code = ".($newdefaultvatcode ?
"'".$this->db->escape($newdefaultvatcode).
"'" :
"null").
",";
2753 $sql .=
" price_label = ".(!empty($price_label) ?
"'".$this->db->escape($price_label).
"'" :
"null").
",";
2754 $sql .=
" tva_tx = ".(float)
price2num($newvat).
",";
2755 $sql .=
" recuperableonly = '".$this->db->escape($newnpr).
"'";
2756 $sql .=
" WHERE rowid = ".((int) $id);
2758 dol_syslog(get_class($this).
"::update_price", LOG_DEBUG);
2759 $resql = $this->db->query($sql);
2761 $this->multiprices[$level] = $price;
2762 $this->multiprices_ttc[$level] = $price_ttc;
2763 $this->multiprices_min[$level] = $price_min;
2764 $this->multiprices_min_ttc[$level] = $price_min_ttc;
2765 $this->multiprices_base_type[$level] = $newpricebase;
2766 $this->multiprices_default_vat_code[$level] = $newdefaultvatcode;
2767 $this->multiprices_tva_tx[$level] = $newvat;
2768 $this->multiprices_recuperableonly[$level] = $newnpr;
2770 $this->
price = $price;
2771 $this->price_label = $price_label;
2772 $this->price_ttc = $price_ttc;
2773 $this->price_min = $price_min;
2774 $this->price_min_ttc = $price_min_ttc;
2775 $this->price_base_type = $newpricebase;
2776 $this->default_vat_code = $newdefaultvatcode;
2777 $this->tva_tx = $newvat;
2778 $this->tva_npr = $newnpr;
2781 $this->localtax1_tx = $localtax1;
2782 $this->localtax2_tx = $localtax2;
2783 $this->localtax1_type = $localtaxtype1;
2784 $this->localtax2_type = $localtaxtype2;
2787 $this->price_by_qty = $newpbq;
2791 if (!empty(array_diff_assoc($newPriceData, $lastPriceData)) || !
getDolGlobalString(
'PRODUIT_MULTIPRICES')) {
2795 $this->level = $level;
2799 $result = $this->
call_trigger(
'PRODUCT_PRICE_MODIFY', $user);
2801 $this->db->rollback();
2807 $this->db->commit();
2809 $this->db->rollback();
2810 $this->error = $this->db->lasterror();
2829 $this->fk_price_expression = $expression_id;
2831 return $this->
update($this->
id, $user);
2846 public function fetch($id = 0, $ref =
'', $ref_ext =
'', $barcode =
'', $ignore_expression = 0, $ignore_price_load = 0, $ignore_lang_load = 0)
2848 include_once DOL_DOCUMENT_ROOT.
'/core/lib/company.lib.php';
2852 dol_syslog(get_class($this).
"::fetch id=".$id.
" ref=".$ref.
" ref_ext=".$ref_ext);
2855 if (!$id && !$ref && !$ref_ext && !$barcode) {
2856 $this->error =
'ErrorWrongParameters';
2857 dol_syslog(get_class($this).
"::fetch ".$this->error, LOG_ERR);
2861 $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,";
2862 $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,";
2863 $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,";
2864 $sql .=
" p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.last_main_doc,";
2865 $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,";
2867 $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,";
2869 $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,";
2874 $separatedEntityPMP =
false;
2875 $separatedStock =
false;
2876 $visibleWarehousesEntities =
$conf->entity;
2879 $checkPMPPerEntity = $this->db->query(
"SELECT pmp FROM " . $this->db->prefix() .
"product_perentity WHERE fk_product = ".((int) $id).
" AND entity = ".(
int)
$conf->entity);
2880 if ($this->db->num_rows($checkPMPPerEntity) > 0) {
2881 $separatedEntityPMP =
true;
2885 $separatedStock =
true;
2886 if (isset($mc->sharings[
'stock']) && !empty($mc->sharings[
'stock'])) {
2887 $visibleWarehousesEntities .=
"," . implode(
",", $mc->sharings[
'stock']);
2890 if ($separatedEntityPMP) {
2891 $sql .=
" ppe.pmp,";
2895 $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,";
2896 $sql .=
" p.fk_price_expression, p.price_autogen, p.model_pdf,";
2897 $sql .=
" p.price_label,";
2898 if ($separatedStock) {
2899 $sql .=
" SUM(sp.reel) as stock";
2903 $sql .=
" FROM ".$this->db->prefix().
"product as p";
2905 $sql .=
" LEFT JOIN " . $this->db->prefix() .
"product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int)
$conf->entity);
2907 if ($separatedStock) {
2908 $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).
"))";
2912 $sql .=
" WHERE p.rowid = ".((int) $id);
2914 $sql .=
" WHERE p.entity IN (".getEntity($this->element).
")";
2916 $sql .=
" AND p.ref = '".$this->db->escape($ref).
"'";
2917 } elseif ($ref_ext) {
2918 $sql .=
" AND p.ref_ext = '".$this->db->escape($ref_ext).
"'";
2919 } elseif ($barcode) {
2920 $sql .=
" AND p.barcode = '".$this->db->escape($barcode).
"'";
2923 if ($separatedStock) {
2924 $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,";
2925 $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,";
2926 $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,";
2927 $sql .=
" p.length, p.length_units, p.width, p.width_units, p.height, p.height_units,";
2928 $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,";
2930 $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,";
2932 $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,";
2934 if ($separatedEntityPMP) {
2935 $sql .=
" ppe.pmp,";
2939 $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,";
2940 $sql .=
" p.fk_price_expression, p.price_autogen, p.model_pdf";
2941 $sql .=
" ,p.price_label";
2942 if (!$separatedStock) {
2943 $sql .=
", p.stock";
2947 $resql = $this->db->query($sql);
2949 unset($this->oldcopy);
2951 if ($this->db->num_rows($resql) > 0) {
2952 $obj = $this->db->fetch_object($resql);
2954 $this->
id = $obj->rowid;
2955 $this->
ref = $obj->ref;
2956 $this->ref_ext = $obj->ref_ext;
2957 $this->label = $obj->label;
2959 $this->url = $obj->url;
2960 $this->note_public = $obj->note_public;
2961 $this->note_private = $obj->note_private;
2962 $this->note = $obj->note_private;
2964 $this->
type = $obj->fk_product_type;
2965 $this->price_label = $obj->price_label;
2966 $this->
status = $obj->tosell;
2967 $this->status_buy = $obj->tobuy;
2968 $this->status_batch = $obj->tobatch;
2969 $this->sell_or_eat_by_mandatory = $obj->sell_or_eat_by_mandatory;
2970 $this->batch_mask = $obj->batch_mask;
2972 $this->customcode = $obj->customcode;
2973 $this->country_id = $obj->fk_country;
2974 $this->country_code =
getCountry($this->country_id,
'2', $this->db);
2975 $this->state_id = $obj->fk_state;
2976 $this->lifetime = $obj->lifetime;
2977 $this->qc_frequency = $obj->qc_frequency;
2978 $this->
price = $obj->price;
2979 $this->price_ttc = $obj->price_ttc;
2980 $this->price_min = $obj->price_min;
2981 $this->price_min_ttc = $obj->price_min_ttc;
2982 $this->price_base_type = $obj->price_base_type;
2983 $this->cost_price = $obj->cost_price;
2984 $this->default_vat_code = $obj->default_vat_code;
2985 $this->tva_tx = $obj->tva_tx;
2987 $this->tva_npr = $obj->tva_npr;
2989 $this->localtax1_tx = $obj->localtax1_tx;
2990 $this->localtax2_tx = $obj->localtax2_tx;
2991 $this->localtax1_type = $obj->localtax1_type;
2992 $this->localtax2_type = $obj->localtax2_type;
2994 $this->finished = $obj->finished;
2995 $this->fk_default_bom = $obj->fk_default_bom;
2997 $this->duration = $obj->duration;
2999 preg_match(
'/(\d+)(\w+)/', $obj->duration, $matches);
3000 $this->duration_value = !empty($matches[1]) ? (int) $matches[1] : 0;
3001 $this->duration_unit = !empty($matches[2]) ? (string) $matches[2] :
null;
3002 $this->canvas = $obj->canvas;
3003 $this->net_measure = $obj->net_measure;
3004 $this->net_measure_units = $obj->net_measure_units;
3005 $this->weight = $obj->weight;
3006 $this->weight_units = $obj->weight_units;
3007 $this->length = $obj->length;
3008 $this->length_units = $obj->length_units;
3009 $this->width = $obj->width;
3010 $this->width_units = $obj->width_units;
3011 $this->height = $obj->height;
3012 $this->height_units = $obj->height_units;
3014 $this->surface = $obj->surface;
3015 $this->surface_units = $obj->surface_units;
3016 $this->volume = $obj->volume;
3017 $this->volume_units = $obj->volume_units;
3018 $this->barcode = $obj->barcode;
3019 $this->barcode_type = $obj->fk_barcode_type;
3021 $this->accountancy_code_buy = $obj->accountancy_code_buy;
3022 $this->accountancy_code_buy_intra = $obj->accountancy_code_buy_intra;
3023 $this->accountancy_code_buy_export = $obj->accountancy_code_buy_export;
3024 $this->accountancy_code_sell = $obj->accountancy_code_sell;
3025 $this->accountancy_code_sell_intra = $obj->accountancy_code_sell_intra;
3026 $this->accountancy_code_sell_export = $obj->accountancy_code_sell_export;
3028 $this->fk_default_warehouse = $obj->fk_default_warehouse;
3029 $this->fk_default_workstation = $obj->fk_default_workstation;
3030 $this->seuil_stock_alerte = $obj->seuil_stock_alerte;
3031 $this->desiredstock = $obj->desiredstock;
3032 $this->stock_reel = $obj->stock;
3033 $this->pmp = $obj->pmp;
3035 $this->date_creation = $obj->datec;
3036 $this->date_modification = $obj->tms;
3037 $this->import_key = $obj->import_key;
3038 $this->entity = $obj->entity;
3040 $this->ref_ext = $obj->ref_ext;
3041 $this->fk_price_expression = $obj->fk_price_expression;
3042 $this->fk_unit = $obj->fk_unit;
3043 $this->price_autogen = $obj->price_autogen;
3044 $this->model_pdf = $obj->model_pdf;
3045 $this->last_main_doc = $obj->last_main_doc;
3047 $this->mandatory_period = $obj->mandatory_period;
3049 $this->db->free($resql);
3062 for ($i = 1; $i <= $produit_multiprices_limit; $i++) {
3063 $sql =
"SELECT price, price_ttc, price_min, price_min_ttc,";
3064 $sql .=
" price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid, recuperableonly";
3065 $sql .=
" ,price_label";
3066 $sql .=
" FROM ".$this->db->prefix().
"product_price";
3067 $sql .=
" WHERE entity IN (".getEntity(
'productprice').
")";
3068 $sql .=
" AND price_level=".((int) $i);
3069 $sql .=
" AND fk_product = ".((int) $this->
id);
3070 $sql .=
" ORDER BY date_price DESC, rowid DESC";
3072 $resql = $this->db->query($sql);
3074 $result = $this->db->fetch_array($resql);
3076 $this->multiprices[$i] = $result ? $result[
"price"] :
null;
3077 $this->multiprices_ttc[$i] = $result ? $result[
"price_ttc"] :
null;
3078 $this->multiprices_min[$i] = $result ? $result[
"price_min"] :
null;
3079 $this->multiprices_min_ttc[$i] = $result ? $result[
"price_min_ttc"] :
null;
3080 $this->multiprices_base_type[$i] = $result ? $result[
"price_base_type"] :
null;
3082 $this->multiprices_tva_tx[$i] = $result ? $result[
"tva_tx"].($result ?
' ('.$result[
'default_vat_code'].
')' :
'') :
null;
3083 $this->multiprices_recuperableonly[$i] = $result ? $result[
"recuperableonly"] :
null;
3122 $this->error = $this->db->lasterror;
3128 } elseif (
getDolGlobalString(
'PRODUIT_CUSTOMER_PRICES_BY_QTY') && empty($ignore_price_load)) {
3129 $sql =
"SELECT price, price_ttc, price_min, price_min_ttc,";
3130 $sql .=
" price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid";
3131 $sql .=
" FROM ".$this->db->prefix().
"product_price";
3132 $sql .=
" WHERE fk_product = ".((int) $this->
id);
3133 $sql .=
" ORDER BY date_price DESC, rowid DESC";
3136 $resql = $this->db->query($sql);
3138 $result = $this->db->fetch_array($resql);
3142 $this->prices_by_qty[0] = $result[
"price_by_qty"];
3143 $this->prices_by_qty_id[0] = $result[
"rowid"];
3145 if ($this->prices_by_qty[0] == 1) {
3146 $sql =
"SELECT rowid,price, unitprice, quantity, remise_percent, remise, remise, price_base_type";
3147 $sql .=
" FROM ".$this->db->prefix().
"product_price_by_qty";
3148 $sql .=
" WHERE fk_product_price = ".((int) $this->prices_by_qty_id[0]);
3149 $sql .=
" ORDER BY quantity ASC";
3151 $resql = $this->db->query($sql);
3153 $resultat = array();
3155 while ($result = $this->db->fetch_array($resql)) {
3156 $resultat[$ii] = array();
3157 $resultat[$ii][
"rowid"] = $result[
"rowid"];
3158 $resultat[$ii][
"price"] = $result[
"price"];
3159 $resultat[$ii][
"unitprice"] = $result[
"unitprice"];
3160 $resultat[$ii][
"quantity"] = $result[
"quantity"];
3161 $resultat[$ii][
"remise_percent"] = $result[
"remise_percent"];
3163 $resultat[$ii][
"price_base_type"] = $result[
"price_base_type"];
3166 $this->prices_by_qty_list[0] = $resultat;
3168 $this->error = $this->db->lasterror;
3174 $this->error = $this->db->lasterror;
3177 } elseif (
getDolGlobalString(
'PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') && empty($ignore_price_load)) {
3179 for ($i = 1; $i <= $produit_multiprices_limit; $i++) {
3180 $sql =
"SELECT price, price_ttc, price_min, price_min_ttc,";
3181 $sql .=
" price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid, recuperableonly";
3182 $sql .=
" FROM ".$this->db->prefix().
"product_price";
3183 $sql .=
" WHERE entity IN (".getEntity(
'productprice').
")";
3184 $sql .=
" AND price_level=".((int) $i);
3185 $sql .=
" AND fk_product = ".((int) $this->
id);
3186 $sql .=
" ORDER BY date_price DESC, rowid DESC";
3188 $resql = $this->db->query($sql);
3190 $this->error = $this->db->lasterror;
3192 } elseif ($result = $this->db->fetch_array($resql)) {
3193 $this->multiprices[$i] = (!empty($result[
"price"]) ? $result[
"price"] : 0);
3194 $this->multiprices_ttc[$i] = (!empty($result[
"price_ttc"]) ? $result[
"price_ttc"] : 0);
3195 $this->multiprices_min[$i] = (!empty($result[
"price_min"]) ? $result[
"price_min"] : 0);
3196 $this->multiprices_min_ttc[$i] = (!empty($result[
"price_min_ttc"]) ? $result[
"price_min_ttc"] : 0);
3197 $this->multiprices_base_type[$i] = (!empty($result[
"price_base_type"]) ? $result[
"price_base_type"] :
'');
3199 $this->multiprices_tva_tx[$i] = (!empty($result[
"tva_tx"]) ? $result[
"tva_tx"] : 0);
3200 $this->multiprices_recuperableonly[$i] = (!empty($result[
"recuperableonly"]) ? $result[
"recuperableonly"] : 0);
3203 $this->prices_by_qty[$i] = (!empty($result[
"price_by_qty"]) ? $result[
"price_by_qty"] : 0);
3204 $this->prices_by_qty_id[$i] = (!empty($result[
"rowid"]) ? $result[
"rowid"] : 0);
3206 if ($this->prices_by_qty[$i] == 1) {
3207 $sql =
"SELECT rowid, price, unitprice, quantity, remise_percent, remise, price_base_type";
3208 $sql .=
" FROM ".$this->db->prefix().
"product_price_by_qty";
3209 $sql .=
" WHERE fk_product_price = ".((int) $this->prices_by_qty_id[$i]);
3210 $sql .=
" ORDER BY quantity ASC";
3212 $resql = $this->db->query($sql);
3214 $resultat = array();
3216 while ($result = $this->db->fetch_array($resql)) {
3217 $resultat[$ii] = array();
3218 $resultat[$ii][
"rowid"] = $result[
"rowid"];
3219 $resultat[$ii][
"price"] = $result[
"price"];
3220 $resultat[$ii][
"unitprice"] = $result[
"unitprice"];
3221 $resultat[$ii][
"quantity"] = $result[
"quantity"];
3222 $resultat[$ii][
"remise_percent"] = $result[
"remise_percent"];
3223 $resultat[$ii][
"remise"] = $result[
"remise"];
3224 $resultat[$ii][
"price_base_type"] = $result[
"price_base_type"];
3227 $this->prices_by_qty_list[$i] = $resultat;
3229 $this->error = $this->db->lasterror;
3237 if (isModEnabled(
'dynamicprices') && !empty($this->fk_price_expression) && empty($ignore_expression)) {
3238 include_once DOL_DOCUMENT_ROOT.
'/product/dynamic_price/class/price_parser.class.php';
3240 $price_result = $priceparser->parseProduct($this);
3241 if ($price_result >= 0) {
3242 $this->
price = $price_result;
3244 $this->price_ttc = (float)
price2num($this->
price) * (1 + ($this->tva_tx / 100));
3245 $this->price_ttc = (float)
price2num($this->price_ttc,
'MU');
3251 $this->stock_warehouse = array();
3258 $this->error = $this->db->lasterror();
3273 global $user, $hookmanager, $action;
3277 foreach (array(
'toconsume',
'consumed',
'toproduce',
'produced') as $role) {
3278 $this->stats_mo[
'customers_'.$role] = 0;
3279 $this->stats_mo[
'nb_'.$role] = 0;
3280 $this->stats_mo[
'qty_'.$role] = 0;
3282 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,";
3283 $sql .=
" SUM(mp.qty) as qty";
3284 $sql .=
" FROM ".$this->db->prefix().
"mrp_mo as c";
3285 $sql .=
" INNER JOIN ".$this->db->prefix().
"mrp_production as mp ON mp.fk_mo=c.rowid";
3286 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3287 $sql .=
" INNER JOIN ".$this->db->prefix().
"societe_commerciaux as sc ON sc.fk_soc=c.fk_soc AND sc.fk_user = ".((int) $user->id);
3290 $sql .=
" c.entity IN (".getEntity(
'mo').
")";
3292 $sql .=
" AND mp.fk_product = ".((int) $this->
id);
3293 $sql .=
" AND mp.role ='".$this->db->escape($role).
"'";
3295 $sql .=
" AND c.fk_soc = ".((int) $socid);
3298 $result = $this->db->query($sql);
3300 $obj = $this->db->fetch_object($result);
3301 $this->stats_mo[
'customers_'.$role] = $obj->nb_customers ? $obj->nb_customers : 0;
3302 $this->stats_mo[
'nb_'.$role] = $obj->nb ? $obj->nb : 0;
3303 $this->stats_mo[
'qty_'.$role] = $obj->qty ?
price2num($obj->qty,
'MS') : 0;
3305 $this->error = $this->db->error();
3310 if (!empty($error)) {
3314 $parameters = array(
'socid' => $socid);
3315 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerMO', $parameters, $this, $action);
3317 $this->stats_mo = $hookmanager->resArray[
'stats_mo'];
3333 global $hookmanager, $action;
3337 $this->stats_bom[
'nb_toproduce'] = 0;
3338 $this->stats_bom[
'nb_toconsume'] = 0;
3339 $this->stats_bom[
'qty_toproduce'] = 0;
3340 $this->stats_bom[
'qty_toconsume'] = 0;
3342 $sql =
"SELECT COUNT(DISTINCT b.rowid) as nb_toproduce,";
3343 $sql .=
" SUM(b.qty) as qty_toproduce";
3344 $sql .=
" FROM ".$this->db->prefix().
"bom_bom as b";
3345 $sql .=
" INNER JOIN ".$this->db->prefix().
"bom_bomline as bl ON bl.fk_bom=b.rowid";
3347 $sql .=
" b.entity IN (".getEntity(
'bom').
")";
3348 $sql .=
" AND b.fk_product =".((int) $this->
id);
3349 $sql .=
" GROUP BY b.rowid";
3351 $result = $this->db->query($sql);
3353 $obj = $this->db->fetch_object($result);
3354 $this->stats_bom[
'nb_toproduce'] = !empty($obj->nb_toproduce) ? $obj->nb_toproduce : 0;
3355 $this->stats_bom[
'qty_toproduce'] = !empty($obj->qty_toproduce) ?
price2num($obj->qty_toproduce) : 0;
3357 $this->error = $this->db->error();
3361 $sql =
"SELECT COUNT(DISTINCT bl.rowid) as nb_toconsume,";
3362 $sql .=
" SUM(bl.qty) as qty_toconsume";
3363 $sql .=
" FROM ".$this->db->prefix().
"bom_bom as b";
3364 $sql .=
" INNER JOIN ".$this->db->prefix().
"bom_bomline as bl ON bl.fk_bom=b.rowid";
3366 $sql .=
" b.entity IN (".getEntity(
'bom').
")";
3367 $sql .=
" AND bl.fk_product =".((int) $this->
id);
3369 $result = $this->db->query($sql);
3371 $obj = $this->db->fetch_object($result);
3372 $this->stats_bom[
'nb_toconsume'] = !empty($obj->nb_toconsume) ? $obj->nb_toconsume : 0;
3373 $this->stats_bom[
'qty_toconsume'] = !empty($obj->qty_toconsume) ?
price2num($obj->qty_toconsume) : 0;
3375 $this->error = $this->db->error();
3379 if (!empty($error)) {
3383 $parameters = array(
'socid' => $socid);
3384 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerMO', $parameters, $this, $action);
3386 $this->stats_bom = $hookmanager->resArray[
'stats_bom'];
3402 global $user, $hookmanager, $action;
3404 $sql =
"SELECT COUNT(DISTINCT p.fk_soc) as nb_customers, COUNT(DISTINCT p.rowid) as nb,";
3405 $sql .=
" COUNT(pd.rowid) as nb_rows, SUM(pd.qty) as qty";
3406 $sql .=
" FROM ".$this->db->prefix().
"propaldet as pd";
3407 $sql .=
", ".$this->db->prefix().
"propal as p";
3408 $sql .=
", ".$this->db->prefix().
"societe as s";
3409 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3410 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3412 $sql .=
" WHERE p.rowid = pd.fk_propal";
3413 $sql .=
" AND p.fk_soc = s.rowid";
3414 $sql .=
" AND p.entity IN (".getEntity(
'propal').
")";
3415 $sql .=
" AND pd.fk_product = ".((int) $this->
id);
3416 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3417 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3421 $sql .=
" AND p.fk_soc = ".((int) $socid);
3424 $result = $this->db->query($sql);
3426 $obj = $this->db->fetch_object($result);
3427 $this->stats_propale[
'customers'] = $obj->nb_customers;
3428 $this->stats_propale[
'nb'] = $obj->nb;
3429 $this->stats_propale[
'rows'] = $obj->nb_rows;
3430 $this->stats_propale[
'qty'] = $obj->qty ? $obj->qty : 0;
3435 if (is_array($TFather) && !empty($TFather)) {
3436 foreach ($TFather as &$fatherData) {
3437 $pFather =
new Product($this->db);
3438 $pFather->id = $fatherData[
'id'];
3439 $qtyCoef = $fatherData[
'qty'];
3441 if ($fatherData[
'incdec']) {
3442 $pFather->load_stats_propale($socid);
3444 $this->stats_propale[
'customers'] += $pFather->stats_propale[
'customers'];
3445 $this->stats_propale[
'nb'] += $pFather->stats_propale[
'nb'];
3446 $this->stats_propale[
'rows'] += $pFather->stats_propale[
'rows'];
3447 $this->stats_propale[
'qty'] += $pFather->stats_propale[
'qty'] * $qtyCoef;
3453 $parameters = array(
'socid' => $socid);
3454 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerProposal', $parameters, $this, $action);
3456 $this->stats_propale = $hookmanager->resArray[
'stats_propale'];
3461 $this->error = $this->db->error();
3477 global $user, $hookmanager, $action;
3479 $sql =
"SELECT COUNT(DISTINCT p.fk_soc) as nb_suppliers, COUNT(DISTINCT p.rowid) as nb,";
3480 $sql .=
" COUNT(pd.rowid) as nb_rows, SUM(pd.qty) as qty";
3481 $sql .=
" FROM ".$this->db->prefix().
"supplier_proposaldet as pd";
3482 $sql .=
", ".$this->db->prefix().
"supplier_proposal as p";
3483 $sql .=
", ".$this->db->prefix().
"societe as s";
3484 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3485 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3487 $sql .=
" WHERE p.rowid = pd.fk_supplier_proposal";
3488 $sql .=
" AND p.fk_soc = s.rowid";
3489 $sql .=
" AND p.entity IN (".getEntity(
'supplier_proposal').
")";
3490 $sql .=
" AND pd.fk_product = ".((int) $this->
id);
3491 if (!$user->hasRight(
'societe',
'client',
'voir')) {
3492 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3496 $sql .=
" AND p.fk_soc = ".((int) $socid);
3499 $result = $this->db->query($sql);
3501 $obj = $this->db->fetch_object($result);
3502 $this->stats_proposal_supplier[
'suppliers'] = $obj->nb_suppliers;
3503 $this->stats_proposal_supplier[
'nb'] = $obj->nb;
3504 $this->stats_proposal_supplier[
'rows'] = $obj->nb_rows;
3505 $this->stats_proposal_supplier[
'qty'] = $obj->qty ? $obj->qty : 0;
3507 $parameters = array(
'socid' => $socid);
3508 $reshook = $hookmanager->executeHooks(
'loadStatsSupplierProposal', $parameters, $this, $action);
3510 $this->stats_proposal_supplier = $hookmanager->resArray[
'stats_proposal_supplier'];
3515 $this->error = $this->db->error();
3533 global $user, $hookmanager, $action;
3535 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,";
3536 $sql .=
" COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty";
3537 $sql .=
" FROM ".$this->db->prefix().
"commandedet as cd";
3538 $sql .=
", ".$this->db->prefix().
"commande as c";
3539 $sql .=
", ".$this->db->prefix().
"societe as s";
3540 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3541 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3543 $sql .=
" WHERE c.rowid = cd.fk_commande";
3544 $sql .=
" AND c.fk_soc = s.rowid";
3545 $sql .=
" AND c.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'commande').
")";
3546 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
3547 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3548 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3551 $sql .=
" AND c.fk_soc = ".((int) $socid);
3553 if ($filtrestatut !=
'') {
3554 $sql .=
" AND c.fk_statut in (".$this->db->sanitize($filtrestatut).
")";
3557 $result = $this->db->query($sql);
3559 $obj = $this->db->fetch_object($result);
3560 $this->stats_commande[
'customers'] = $obj->nb_customers;
3561 $this->stats_commande[
'nb'] = $obj->nb;
3562 $this->stats_commande[
'rows'] = $obj->nb_rows;
3563 $this->stats_commande[
'qty'] = $obj->qty ? $obj->qty : 0;
3568 if (is_array($TFather) && !empty($TFather)) {
3569 foreach ($TFather as &$fatherData) {
3570 $pFather =
new Product($this->db);
3571 $pFather->id = $fatherData[
'id'];
3572 $qtyCoef = $fatherData[
'qty'];
3574 if ($fatherData[
'incdec']) {
3575 $pFather->load_stats_commande($socid, $filtrestatut);
3577 $this->stats_commande[
'customers'] += $pFather->stats_commande[
'customers'];
3578 $this->stats_commande[
'nb'] += $pFather->stats_commande[
'nb'];
3579 $this->stats_commande[
'rows'] += $pFather->stats_commande[
'rows'];
3580 $this->stats_commande[
'qty'] += $pFather->stats_commande[
'qty'] * $qtyCoef;
3592 $sql =
"SELECT SUM(".$this->db->ifsql(
'f.type=2', -1, 1).
" * fd.qty) as count FROM ".$this->db->prefix().
"facturedet as fd ";
3593 $sql .=
" JOIN ".$this->db->prefix().
"facture as f ON fd.fk_facture = f.rowid";
3594 $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'))";
3595 $sql .=
" JOIN ".$this->db->prefix().
"commande as c ON el.fk_source = c.rowid";
3596 $sql .=
" WHERE c.fk_statut IN (".$this->db->sanitize($filtrestatut).
") AND c.facture = 0 AND fd.fk_product = ".((int) $this->
id);
3598 dol_syslog(__METHOD__.
":: sql $sql", LOG_NOTICE);
3599 $resql = $this->db->query($sql);
3601 if ($this->db->num_rows($resql) > 0) {
3602 $obj = $this->db->fetch_object($resql);
3603 $adeduire += $obj->count;
3607 $this->stats_commande[
'qty'] -= $adeduire;
3610 include_once DOL_DOCUMENT_ROOT.
'/compta/facture/class/facture.class.php';
3614 $sql =
"SELECT sum(".$this->db->ifsql(
'f.type=2', -1, 1).
" * fd.qty) as count FROM ".MAIN_DB_PREFIX.
"facturedet as fd ";
3615 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"facture as f ON fd.fk_facture = f.rowid";
3616 $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'))";
3617 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"commande as c ON el.fk_source = c.rowid";
3618 $sql .=
" WHERE c.fk_statut IN (".$this->db->sanitize($filtrestatut).
") AND f.fk_statut > ".
Facture::STATUS_DRAFT.
" AND fd.fk_product = ".((int) $this->
id);
3620 dol_syslog(__METHOD__.
":: sql $sql", LOG_NOTICE);
3621 $resql = $this->db->query($sql);
3623 if ($this->db->num_rows($resql) > 0) {
3624 $obj = $this->db->fetch_object($resql);
3625 $adeduire += $obj->count;
3628 $this->error = $this->db->error();
3632 $this->stats_commande[
'qty'] -= $adeduire;
3636 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3637 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerOrder', $parameters, $this, $action);
3639 $this->stats_commande = $hookmanager->resArray[
'stats_commande'];
3643 $this->error = $this->db->error();
3661 global $user, $hookmanager, $action;
3663 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_suppliers, COUNT(DISTINCT c.rowid) as nb,";
3664 $sql .=
" COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty";
3665 $sql .=
" FROM ".$this->db->prefix().
"commande_fournisseurdet as cd";
3666 $sql .=
", ".$this->db->prefix().
"commande_fournisseur as c";
3667 $sql .=
", ".$this->db->prefix().
"societe as s";
3668 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3669 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3671 $sql .=
" WHERE c.rowid = cd.fk_commande";
3672 $sql .=
" AND c.fk_soc = s.rowid";
3673 $sql .=
" AND c.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'supplier_order').
")";
3674 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
3675 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3676 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3679 $sql .=
" AND c.fk_soc = ".((int) $socid);
3681 if ($filtrestatut !=
'') {
3682 $sql .=
" AND c.fk_statut in (".$this->db->sanitize($filtrestatut).
")";
3684 if (!empty($dateofvirtualstock)) {
3685 $sql .=
" AND c.date_livraison <= '".$this->db->idate($dateofvirtualstock).
"'";
3688 $result = $this->db->query($sql);
3690 $obj = $this->db->fetch_object($result);
3691 $this->stats_commande_fournisseur[
'suppliers'] = $obj->nb_suppliers;
3692 $this->stats_commande_fournisseur[
'nb'] = $obj->nb;
3693 $this->stats_commande_fournisseur[
'rows'] = $obj->nb_rows;
3694 $this->stats_commande_fournisseur[
'qty'] = $obj->qty ? $obj->qty : 0;
3696 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3697 $reshook = $hookmanager->executeHooks(
'loadStatsSupplierOrder', $parameters, $this, $action);
3699 $this->stats_commande_fournisseur = $hookmanager->resArray[
'stats_commande_fournisseur'];
3704 $this->error = $this->db->error().
' sql='.$sql;
3719 public function load_stats_sending($socid = 0, $filtrestatut =
'', $forVirtualStock = 0, $filterShipmentStatus =
'')
3722 global $user, $hookmanager, $action;
3724 $sql =
"SELECT COUNT(DISTINCT e.fk_soc) as nb_customers, COUNT(DISTINCT e.rowid) as nb,";
3725 $sql .=
" COUNT(ed.rowid) as nb_rows, SUM(ed.qty) as qty";
3726 $sql .=
" FROM ".$this->db->prefix().
"expeditiondet as ed";
3727 $sql .=
", ".$this->db->prefix().
"commandedet as cd";
3728 $sql .=
", ".$this->db->prefix().
"commande as c";
3729 $sql .=
", ".$this->db->prefix().
"expedition as e";
3730 $sql .=
", ".$this->db->prefix().
"societe as s";
3731 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3732 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3734 $sql .=
" WHERE e.rowid = ed.fk_expedition";
3735 $sql .=
" AND c.rowid = cd.fk_commande";
3736 $sql .=
" AND e.fk_soc = s.rowid";
3737 $sql .=
" AND e.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'expedition').
")";
3738 $sql .=
" AND ed.fk_elementdet = cd.rowid";
3739 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
3740 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3741 $sql .=
" AND e.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3744 $sql .=
" AND e.fk_soc = ".((int) $socid);
3746 if ($filtrestatut !=
'') {
3747 $sql .=
" AND c.fk_statut IN (".$this->db->sanitize($filtrestatut).
")";
3749 if (!empty($filterShipmentStatus)) {
3750 $sql .=
" AND e.fk_statut IN (".$this->db->sanitize($filterShipmentStatus).
")";
3753 $result = $this->db->query($sql);
3755 $obj = $this->db->fetch_object($result);
3756 $this->stats_expedition[
'customers'] = $obj->nb_customers;
3757 $this->stats_expedition[
'nb'] = $obj->nb;
3758 $this->stats_expedition[
'rows'] = $obj->nb_rows;
3759 $this->stats_expedition[
'qty'] = $obj->qty ? $obj->qty : 0;
3764 if (is_array($TFather) && !empty($TFather)) {
3765 foreach ($TFather as &$fatherData) {
3766 $pFather =
new Product($this->db);
3767 $pFather->id = $fatherData[
'id'];
3768 $qtyCoef = $fatherData[
'qty'];
3770 if ($fatherData[
'incdec']) {
3771 $pFather->load_stats_sending($socid, $filtrestatut, $forVirtualStock);
3773 $this->stats_expedition[
'customers'] += $pFather->stats_expedition[
'customers'];
3774 $this->stats_expedition[
'nb'] += $pFather->stats_expedition[
'nb'];
3775 $this->stats_expedition[
'rows'] += $pFather->stats_expedition[
'rows'];
3776 $this->stats_expedition[
'qty'] += $pFather->stats_expedition[
'qty'] * $qtyCoef;
3782 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock,
'filterShipmentStatus' => $filterShipmentStatus);
3783 $reshook = $hookmanager->executeHooks(
'loadStatsSending', $parameters, $this, $action);
3785 $this->stats_expedition = $hookmanager->resArray[
'stats_expedition'];
3790 $this->error = $this->db->error();
3805 public function load_stats_reception($socid = 0, $filtrestatut =
'', $forVirtualStock = 0, $dateofvirtualstock =
null)
3808 global $user, $hookmanager, $action;
3810 $sql =
"SELECT COUNT(DISTINCT cf.fk_soc) as nb_suppliers, COUNT(DISTINCT cf.rowid) as nb,";
3811 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(fd.qty) as qty";
3812 $sql .=
" FROM ".$this->db->prefix().
"receptiondet_batch as fd";
3813 $sql .=
", ".$this->db->prefix().
"commande_fournisseur as cf";
3814 $sql .=
", ".$this->db->prefix().
"societe as s";
3815 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3816 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3818 $sql .=
" WHERE cf.rowid = fd.fk_element";
3819 $sql .=
" AND cf.fk_soc = s.rowid";
3820 $sql .=
" AND cf.entity IN (".getEntity($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ?
'stock' :
'supplier_order').
")";
3821 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
3822 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3823 $sql .=
" AND cf.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3826 $sql .=
" AND cf.fk_soc = ".((int) $socid);
3828 if ($filtrestatut !=
'') {
3829 $sql .=
" AND cf.fk_statut IN (".$this->db->sanitize($filtrestatut).
")";
3831 if (!empty($dateofvirtualstock)) {
3832 $sql .=
" AND fd.datec <= '".$this->db->idate($dateofvirtualstock).
"'";
3835 $result = $this->db->query($sql);
3837 $obj = $this->db->fetch_object($result);
3838 $this->stats_reception[
'suppliers'] = $obj->nb_suppliers;
3839 $this->stats_reception[
'nb'] = $obj->nb;
3840 $this->stats_reception[
'rows'] = $obj->nb_rows;
3841 $this->stats_reception[
'qty'] = $obj->qty ? $obj->qty : 0;
3843 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3844 $reshook = $hookmanager->executeHooks(
'loadStatsReception', $parameters, $this, $action);
3846 $this->stats_reception = $hookmanager->resArray[
'stats_reception'];
3851 $this->error = $this->db->error();
3867 public function load_stats_inproduction($socid = 0, $filtrestatut =
'', $forVirtualStock = 0, $dateofvirtualstock =
null, $warehouseid = 0)
3870 global $user, $hookmanager, $action;
3872 $serviceStockIsEnabled = isModEnabled(
"service") &&
getDolGlobalString(
'STOCK_SUPPORTS_SERVICES');
3874 $sql =
"SELECT COUNT(DISTINCT m.fk_soc) as nb_customers, COUNT(DISTINCT m.rowid) as nb,";
3875 $sql .=
" COUNT(mp.rowid) as nb_rows, SUM(mp.qty) as qty, role";
3876 $sql .=
" FROM ".$this->db->prefix().
"mrp_production as mp";
3877 $sql .=
", ".$this->db->prefix().
"mrp_mo as m";
3878 $sql .=
" LEFT JOIN ".$this->db->prefix().
"societe as s ON s.rowid = m.fk_soc";
3879 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3880 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
3882 $sql .=
" WHERE m.rowid = mp.fk_mo";
3883 $sql .=
" AND m.entity IN (".getEntity(($forVirtualStock &&
getDolGlobalString(
'STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE')) ?
'stock' :
'mrp').
")";
3884 $sql .=
" AND mp.fk_product = ".((int) $this->
id);
3885 $sql .=
" AND (mp.disable_stock_change IN (0) OR mp.disable_stock_change IS NULL)";
3886 if (!$user->hasRight(
'societe',
'client',
'voir') && !$forVirtualStock) {
3887 $sql .=
" AND m.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
3890 $sql .=
" AND m.fk_soc = ".((int) $socid);
3892 if ($filtrestatut !=
'') {
3893 $sql .=
" AND m.status IN (".$this->db->sanitize($filtrestatut).
")";
3895 if (!empty($dateofvirtualstock)) {
3896 $sql .=
" AND m.date_valid <= '".$this->db->idate($dateofvirtualstock).
"'";
3898 if (!$serviceStockIsEnabled) {
3899 $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))";
3901 if (!empty($warehouseid)) {
3902 $sql .=
" AND m.fk_warehouse = ".((int) $warehouseid);
3904 $sql .=
" GROUP BY role";
3907 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] = 0;
3909 $this->stats_mrptoconsume[
'customers'] = 0;
3910 $this->stats_mrptoconsume[
'nb'] = 0;
3911 $this->stats_mrptoconsume[
'rows'] = 0;
3912 $this->stats_mrptoconsume[
'qty'] = 0;
3913 $this->stats_mrptoproduce[
'customers'] = 0;
3914 $this->stats_mrptoproduce[
'nb'] = 0;
3915 $this->stats_mrptoproduce[
'rows'] = 0;
3916 $this->stats_mrptoproduce[
'qty'] = 0;
3919 $result = $this->db->query($sql);
3921 while ($obj = $this->db->fetch_object($result)) {
3922 if ($obj->role ==
'toconsume' && empty($warehouseid)) {
3923 $this->stats_mrptoconsume[
'customers'] += $obj->nb_customers;
3924 $this->stats_mrptoconsume[
'nb'] += $obj->nb;
3925 $this->stats_mrptoconsume[
'rows'] += $obj->nb_rows;
3926 $this->stats_mrptoconsume[
'qty'] += ($obj->qty ? $obj->qty : 0);
3928 if ($obj->role ==
'consumed' && empty($warehouseid)) {
3932 $this->stats_mrptoconsume[
'qty'] -= ($obj->qty ? $obj->qty : 0);
3934 if ($obj->role ==
'toproduce') {
3936 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] += ($obj->qty ? $obj->qty : 0);
3938 $this->stats_mrptoproduce[
'customers'] += $obj->nb_customers;
3939 $this->stats_mrptoproduce[
'nb'] += $obj->nb;
3940 $this->stats_mrptoproduce[
'rows'] += $obj->nb_rows;
3941 $this->stats_mrptoproduce[
'qty'] += ($obj->qty ? $obj->qty : 0);
3944 if ($obj->role ==
'produced') {
3949 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] -= ($obj->qty ? $obj->qty : 0);
3951 $this->stats_mrptoproduce[
'qty'] -= ($obj->qty ? $obj->qty : 0);
3958 if ($this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] < 0) {
3959 $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'] = 0;
3962 if ($this->stats_mrptoconsume[
'qty'] < 0) {
3963 $this->stats_mrptoconsume[
'qty'] = 0;
3965 if ($this->stats_mrptoproduce[
'qty'] < 0) {
3966 $this->stats_mrptoproduce[
'qty'] = 0;
3970 $parameters = array(
'socid' => $socid,
'filtrestatut' => $filtrestatut,
'forVirtualStock' => $forVirtualStock);
3971 $reshook = $hookmanager->executeHooks(
'loadStatsInProduction', $parameters, $this, $action);
3973 $this->stats_mrptoproduce = $hookmanager->resArray[
'stats_mrptoproduce'];
3978 $this->error = $this->db->error();
3993 global $user, $hookmanager, $action;
3995 $sql =
"SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,";
3996 $sql .=
" COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty";
3997 $sql .=
" FROM ".$this->db->prefix().
"contratdet as cd";
3998 $sql .=
", ".$this->db->prefix().
"contrat as c";
3999 $sql .=
", ".$this->db->prefix().
"societe as s";
4000 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4001 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4003 $sql .=
" WHERE c.rowid = cd.fk_contrat";
4004 $sql .=
" AND c.fk_soc = s.rowid";
4005 $sql .=
" AND c.entity IN (".getEntity(
'contract').
")";
4006 $sql .=
" AND cd.fk_product = ".((int) $this->
id);
4007 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4008 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4012 $sql .=
" AND c.fk_soc = ".((int) $socid);
4015 $result = $this->db->query($sql);
4017 $obj = $this->db->fetch_object($result);
4018 $this->stats_contrat[
'customers'] = $obj->nb_customers;
4019 $this->stats_contrat[
'nb'] = $obj->nb;
4020 $this->stats_contrat[
'rows'] = $obj->nb_rows;
4021 $this->stats_contrat[
'qty'] = $obj->qty ? $obj->qty : 0;
4026 if (is_array($TFather) && !empty($TFather)) {
4027 foreach ($TFather as &$fatherData) {
4028 $pFather =
new Product($this->db);
4029 $pFather->id = $fatherData[
'id'];
4030 $qtyCoef = $fatherData[
'qty'];
4032 if ($fatherData[
'incdec']) {
4033 $pFather->load_stats_contrat($socid);
4035 $this->stats_contrat[
'customers'] += $pFather->stats_contrat[
'customers'];
4036 $this->stats_contrat[
'nb'] += $pFather->stats_contrat[
'nb'];
4037 $this->stats_contrat[
'rows'] += $pFather->stats_contrat[
'rows'];
4038 $this->stats_contrat[
'qty'] += $pFather->stats_contrat[
'qty'] * $qtyCoef;
4044 $parameters = array(
'socid' => $socid);
4045 $reshook = $hookmanager->executeHooks(
'loadStatsContract', $parameters, $this, $action);
4047 $this->stats_contrat = $hookmanager->resArray[
'stats_contrat'];
4052 $this->error = $this->db->error().
' sql='.$sql;
4067 global $user, $hookmanager, $action;
4069 $sql =
"SELECT COUNT(DISTINCT f.fk_soc) as nb_customers, COUNT(DISTINCT f.rowid) as nb,";
4070 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(".$this->db->ifsql(
'f.type != 2',
'fd.qty',
'fd.qty * -1').
") as qty";
4071 $sql .=
" FROM ".$this->db->prefix().
"facturedet as fd";
4072 $sql .=
", ".$this->db->prefix().
"facture as f";
4073 $sql .=
", ".$this->db->prefix().
"societe as s";
4074 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4075 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4077 $sql .=
" WHERE f.rowid = fd.fk_facture";
4078 $sql .=
" AND f.fk_soc = s.rowid";
4079 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4080 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
4081 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4082 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4086 $sql .=
" AND f.fk_soc = ".((int) $socid);
4089 $result = $this->db->query($sql);
4091 $obj = $this->db->fetch_object($result);
4092 $this->stats_facture[
'customers'] = $obj->nb_customers;
4093 $this->stats_facture[
'nb'] = $obj->nb;
4094 $this->stats_facture[
'rows'] = $obj->nb_rows;
4095 $this->stats_facture[
'qty'] = $obj->qty ? $obj->qty : 0;
4100 if (is_array($TFather) && !empty($TFather)) {
4101 foreach ($TFather as &$fatherData) {
4102 $pFather =
new Product($this->db);
4103 $pFather->id = $fatherData[
'id'];
4104 $qtyCoef = $fatherData[
'qty'];
4106 if ($fatherData[
'incdec']) {
4107 $pFather->load_stats_facture($socid);
4109 $this->stats_facture[
'customers'] += $pFather->stats_facture[
'customers'];
4110 $this->stats_facture[
'nb'] += $pFather->stats_facture[
'nb'];
4111 $this->stats_facture[
'rows'] += $pFather->stats_facture[
'rows'];
4112 $this->stats_facture[
'qty'] += $pFather->stats_facture[
'qty'] * $qtyCoef;
4118 $parameters = array(
'socid' => $socid);
4119 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerInvoice', $parameters, $this, $action);
4121 $this->stats_facture = $hookmanager->resArray[
'stats_facture'];
4126 $this->error = $this->db->error();
4142 global $user, $hookmanager, $action;
4144 $sql =
"SELECT COUNT(DISTINCT f.fk_soc) as nb_customers, COUNT(DISTINCT f.rowid) as nb,";
4145 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(fd.qty) as qty";
4146 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facturedet_rec as fd";
4147 $sql .=
", ".MAIN_DB_PREFIX.
"facture_rec as f";
4148 $sql .=
", ".MAIN_DB_PREFIX.
"societe as s";
4149 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4150 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
4152 $sql .=
" WHERE f.rowid = fd.fk_facture";
4153 $sql .=
" AND f.fk_soc = s.rowid";
4154 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4155 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
4156 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4157 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4161 $sql .=
" AND f.fk_soc = ".((int) $socid);
4164 $result = $this->db->query($sql);
4166 $obj = $this->db->fetch_object($result);
4167 $this->stats_facturerec[
'customers'] = $obj->nb_customers;
4168 $this->stats_facturerec[
'nb'] = $obj->nb;
4169 $this->stats_facturerec[
'rows'] = $obj->nb_rows;
4170 $this->stats_facturerec[
'qty'] = $obj->qty ? $obj->qty : 0;
4175 if (is_array($TFather) && !empty($TFather)) {
4176 foreach ($TFather as &$fatherData) {
4177 $pFather =
new Product($this->db);
4178 $pFather->id = $fatherData[
'id'];
4179 $qtyCoef = $fatherData[
'qty'];
4181 if ($fatherData[
'incdec']) {
4182 $pFather->load_stats_facture($socid);
4184 $this->stats_facturerec[
'customers'] += $pFather->stats_facturerec[
'customers'];
4185 $this->stats_facturerec[
'nb'] += $pFather->stats_facturerec[
'nb'];
4186 $this->stats_facturerec[
'rows'] += $pFather->stats_facturerec[
'rows'];
4187 $this->stats_facturerec[
'qty'] += $pFather->stats_facturerec[
'qty'] * $qtyCoef;
4193 $parameters = array(
'socid' => $socid);
4194 $reshook = $hookmanager->executeHooks(
'loadStatsCustomerInvoiceRec', $parameters, $this, $action);
4196 $this->stats_facturerec = $hookmanager->resArray[
'stats_facturerec'];
4201 $this->error = $this->db->error();
4216 global $user, $hookmanager, $action;
4218 $sql =
"SELECT COUNT(DISTINCT f.fk_soc) as nb_suppliers, COUNT(DISTINCT f.rowid) as nb,";
4219 $sql .=
" COUNT(fd.rowid) as nb_rows, SUM(fd.qty) as qty";
4220 $sql .=
" FROM ".$this->db->prefix().
"facture_fourn_det as fd";
4221 $sql .=
", ".$this->db->prefix().
"facture_fourn as f";
4222 $sql .=
", ".$this->db->prefix().
"societe as s";
4223 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4224 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4226 $sql .=
" WHERE f.rowid = fd.fk_facture_fourn";
4227 $sql .=
" AND f.fk_soc = s.rowid";
4228 $sql .=
" AND f.entity IN (".getEntity(
'facture_fourn').
")";
4229 $sql .=
" AND fd.fk_product = ".((int) $this->
id);
4230 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4231 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4235 $sql .=
" AND f.fk_soc = ".((int) $socid);
4238 $result = $this->db->query($sql);
4240 $obj = $this->db->fetch_object($result);
4241 $this->stats_facture_fournisseur[
'suppliers'] = $obj->nb_suppliers;
4242 $this->stats_facture_fournisseur[
'nb'] = $obj->nb;
4243 $this->stats_facture_fournisseur[
'rows'] = $obj->nb_rows;
4244 $this->stats_facture_fournisseur[
'qty'] = $obj->qty ? $obj->qty : 0;
4246 $parameters = array(
'socid' => $socid);
4247 $reshook = $hookmanager->executeHooks(
'loadStatsSupplierInvoice', $parameters, $this, $action);
4249 $this->stats_facture_fournisseur = $hookmanager->resArray[
'stats_facture_fournisseur'];
4254 $this->error = $this->db->error();
4273 $resql = $this->db->query($sql);
4275 $num = $this->db->num_rows($resql);
4278 $arr = $this->db->fetch_array($resql);
4279 if (is_array($arr)) {
4280 $keyfortab = (string) $arr[1];
4282 $keyfortab = substr($keyfortab, -2);
4285 if ($mode ==
'byunit') {
4286 $tab[$keyfortab] = (empty($tab[$keyfortab]) ? 0 : $tab[$keyfortab]) + $arr[0];
4287 } elseif ($mode ==
'bynumber') {
4288 $tab[$keyfortab] = (empty($tab[$keyfortab]) ? 0 : $tab[$keyfortab]) + $arr[2];
4289 } elseif ($mode ==
'byamount') {
4290 $tab[$keyfortab] = (empty($tab[$keyfortab]) ? 0 : $tab[$keyfortab]) + $arr[2];
4299 $this->error = $this->db->error().
' sql='.$sql;
4306 } elseif ($year == -1) {
4315 for ($j = 0; $j < 12; $j++) {
4317 $idx = ucfirst(
dol_trunc(
dol_print_date(
dol_mktime(12, 0, 0, $month, 1, 1970),
"%b"), 1,
'right',
'UTF-8', 1));
4320 $result[$j] = array($idx, isset($tab[$year.$month]) ? $tab[$year.$month] : 0);
4323 $month =
"0".($month - 1);
4325 $month = substr($month, 1);
4333 return array_reverse($result);
4348 public function get_nb_vente($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4353 $sql =
"SELECT sum(d.qty) as qty, date_format(f.datef, '%Y%m')";
4354 if ($mode ==
'bynumber') {
4355 $sql .=
", count(DISTINCT f.rowid)";
4357 $sql .=
", sum(d.total_ht) as total_ht";
4358 $sql .=
" FROM ".$this->db->prefix().
"facturedet as d, ".$this->db->prefix().
"facture as f, ".$this->db->prefix().
"societe as s";
4359 if ($filteronproducttype >= 0) {
4360 $sql .=
", ".$this->db->prefix().
"product as p";
4362 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4363 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4365 $sql .=
" WHERE f.rowid = d.fk_facture";
4366 if ($this->
id > 0) {
4367 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4369 $sql .=
" AND d.fk_product > 0";
4371 if ($filteronproducttype >= 0) {
4372 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4374 $sql .=
" AND f.fk_soc = s.rowid";
4375 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4376 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4377 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4380 $sql .=
" AND f.fk_soc = $socid";
4382 $sql .= $morefilter;
4383 $sql .=
" GROUP BY date_format(f.datef,'%Y%m')";
4384 $sql .=
" ORDER BY date_format(f.datef,'%Y%m') DESC";
4386 return $this->
_get_stats($sql, $mode, $year);
4401 public function get_nb_achat($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4406 $sql =
"SELECT sum(d.qty) as qty, date_format(f.datef, '%Y%m')";
4407 if ($mode ==
'bynumber') {
4408 $sql .=
", count(DISTINCT f.rowid)";
4410 $sql .=
", sum(d.total_ht) as total_ht";
4411 $sql .=
" FROM ".$this->db->prefix().
"facture_fourn_det as d, ".$this->db->prefix().
"facture_fourn as f, ".$this->db->prefix().
"societe as s";
4412 if ($filteronproducttype >= 0) {
4413 $sql .=
", ".$this->db->prefix().
"product as p";
4415 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4416 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4418 $sql .=
" WHERE f.rowid = d.fk_facture_fourn";
4419 if ($this->
id > 0) {
4420 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4422 $sql .=
" AND d.fk_product > 0";
4424 if ($filteronproducttype >= 0) {
4425 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4427 $sql .=
" AND f.fk_soc = s.rowid";
4428 $sql .=
" AND f.entity IN (".getEntity(
'facture_fourn').
")";
4429 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4430 $sql .=
" AND f.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4433 $sql .=
" AND f.fk_soc = $socid";
4435 $sql .= $morefilter;
4436 $sql .=
" GROUP BY date_format(f.datef,'%Y%m')";
4437 $sql .=
" ORDER BY date_format(f.datef,'%Y%m') DESC";
4439 return $this->
_get_stats($sql, $mode, $year);
4453 public function get_nb_propal($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4458 $sql =
"SELECT sum(d.qty) as qty, date_format(p.datep, '%Y%m')";
4459 if ($mode ==
'bynumber') {
4460 $sql .=
", count(DISTINCT p.rowid)";
4462 $sql .=
", sum(d.total_ht) as total_ht";
4463 $sql .=
" FROM ".$this->db->prefix().
"propaldet as d, ".$this->db->prefix().
"propal as p, ".$this->db->prefix().
"societe as s";
4464 if ($filteronproducttype >= 0) {
4465 $sql .=
", ".$this->db->prefix().
"product as prod";
4467 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4468 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4470 $sql .=
" WHERE p.rowid = d.fk_propal";
4471 if ($this->
id > 0) {
4472 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4474 $sql .=
" AND d.fk_product > 0";
4476 if ($filteronproducttype >= 0) {
4477 $sql .=
" AND prod.rowid = d.fk_product AND prod.fk_product_type = ".((int) $filteronproducttype);
4479 $sql .=
" AND p.fk_soc = s.rowid";
4480 $sql .=
" AND p.entity IN (".getEntity(
'propal').
")";
4481 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4482 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4485 $sql .=
" AND p.fk_soc = ".((int) $socid);
4487 $sql .= $morefilter;
4488 $sql .=
" GROUP BY date_format(p.datep,'%Y%m')";
4489 $sql .=
" ORDER BY date_format(p.datep,'%Y%m') DESC";
4491 return $this->
_get_stats($sql, $mode, $year);
4510 $sql =
"SELECT sum(d.qty) as qty, date_format(p.date_valid, '%Y%m')";
4511 if ($mode ==
'bynumber') {
4512 $sql .=
", count(DISTINCT p.rowid)";
4514 $sql .=
", sum(d.total_ht) as total_ht";
4515 $sql .=
" FROM ".$this->db->prefix().
"supplier_proposaldet as d, ".$this->db->prefix().
"supplier_proposal as p, ".$this->db->prefix().
"societe as s";
4516 if ($filteronproducttype >= 0) {
4517 $sql .=
", ".$this->db->prefix().
"product as prod";
4519 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4520 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4522 $sql .=
" WHERE p.rowid = d.fk_supplier_proposal";
4523 if ($this->
id > 0) {
4524 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4526 $sql .=
" AND d.fk_product > 0";
4528 if ($filteronproducttype >= 0) {
4529 $sql .=
" AND prod.rowid = d.fk_product AND prod.fk_product_type = ".((int) $filteronproducttype);
4531 $sql .=
" AND p.fk_soc = s.rowid";
4532 $sql .=
" AND p.entity IN (".getEntity(
'supplier_proposal').
")";
4533 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4534 $sql .=
" AND p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4537 $sql .=
" AND p.fk_soc = ".((int) $socid);
4539 $sql .= $morefilter;
4540 $sql .=
" GROUP BY date_format(p.date_valid,'%Y%m')";
4541 $sql .=
" ORDER BY date_format(p.date_valid,'%Y%m') DESC";
4543 return $this->
_get_stats($sql, $mode, $year);
4557 public function get_nb_order($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4562 $sql =
"SELECT sum(d.qty) as qty, date_format(c.date_commande, '%Y%m')";
4563 if ($mode ==
'bynumber') {
4564 $sql .=
", count(DISTINCT c.rowid)";
4566 $sql .=
", sum(d.total_ht) as total_ht";
4567 $sql .=
" FROM ".$this->db->prefix().
"commandedet as d, ".$this->db->prefix().
"commande as c, ".$this->db->prefix().
"societe as s";
4568 if ($filteronproducttype >= 0) {
4569 $sql .=
", ".$this->db->prefix().
"product as p";
4571 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4572 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4574 $sql .=
" WHERE c.rowid = d.fk_commande";
4575 if ($this->
id > 0) {
4576 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4578 $sql .=
" AND d.fk_product > 0";
4580 if ($filteronproducttype >= 0) {
4581 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4583 $sql .=
" AND c.fk_soc = s.rowid";
4584 $sql .=
" AND c.entity IN (".getEntity(
'commande').
")";
4585 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4586 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4589 $sql .=
" AND c.fk_soc = ".((int) $socid);
4591 $sql .= $morefilter;
4592 $sql .=
" GROUP BY date_format(c.date_commande,'%Y%m')";
4593 $sql .=
" ORDER BY date_format(c.date_commande,'%Y%m') DESC";
4595 return $this->
_get_stats($sql, $mode, $year);
4614 $sql =
"SELECT sum(d.qty) as qty, date_format(c.date_commande, '%Y%m')";
4615 if ($mode ==
'bynumber') {
4616 $sql .=
", count(DISTINCT c.rowid)";
4618 $sql .=
", sum(d.total_ht) as total_ht";
4619 $sql .=
" FROM ".$this->db->prefix().
"commande_fournisseurdet as d, ".$this->db->prefix().
"commande_fournisseur as c, ".$this->db->prefix().
"societe as s";
4620 if ($filteronproducttype >= 0) {
4621 $sql .=
", ".$this->db->prefix().
"product as p";
4623 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4624 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4626 $sql .=
" WHERE c.rowid = d.fk_commande";
4627 if ($this->
id > 0) {
4628 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4630 $sql .=
" AND d.fk_product > 0";
4632 if ($filteronproducttype >= 0) {
4633 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4635 $sql .=
" AND c.fk_soc = s.rowid";
4636 $sql .=
" AND c.entity IN (".getEntity(
'supplier_order').
")";
4637 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4638 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4641 $sql .=
" AND c.fk_soc = ".((int) $socid);
4643 $sql .= $morefilter;
4644 $sql .=
" GROUP BY date_format(c.date_commande,'%Y%m')";
4645 $sql .=
" ORDER BY date_format(c.date_commande,'%Y%m') DESC";
4647 return $this->
_get_stats($sql, $mode, $year);
4661 public function get_nb_contract($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4666 $sql =
"SELECT sum(d.qty) as qty, date_format(c.date_contrat, '%Y%m')";
4667 if ($mode ==
'bynumber') {
4668 $sql .=
", count(DISTINCT c.rowid)";
4670 $sql .=
", sum(d.total_ht) as total_ht";
4671 $sql .=
" FROM ".$this->db->prefix().
"contratdet as d, ".$this->db->prefix().
"contrat as c, ".$this->db->prefix().
"societe as s";
4672 if ($filteronproducttype >= 0) {
4673 $sql .=
", ".$this->db->prefix().
"product as p";
4675 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4676 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4678 $sql .=
" WHERE c.entity IN (".getEntity(
'contract').
")";
4679 $sql .=
" AND c.rowid = d.fk_contrat";
4681 if ($this->
id > 0) {
4682 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4684 $sql .=
" AND d.fk_product > 0";
4686 if ($filteronproducttype >= 0) {
4687 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4689 $sql .=
" AND c.fk_soc = s.rowid";
4691 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4692 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4695 $sql .=
" AND c.fk_soc = ".((int) $socid);
4697 $sql .= $morefilter;
4698 $sql .=
" GROUP BY date_format(c.date_contrat,'%Y%m')";
4699 $sql .=
" ORDER BY date_format(c.date_contrat,'%Y%m') DESC";
4701 return $this->
_get_stats($sql, $mode, $year);
4715 public function get_nb_mos($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter =
'')
4720 $sql =
"SELECT sum(d.qty), date_format(d.date_valid, '%Y%m')";
4721 if ($mode ==
'bynumber') {
4722 $sql .=
", count(DISTINCT d.rowid)";
4724 $sql .=
" FROM ".$this->db->prefix().
"mrp_mo as d LEFT JOIN ".$this->db->prefix().
"societe as s ON d.fk_soc = s.rowid";
4725 if ($filteronproducttype >= 0) {
4726 $sql .=
", ".$this->db->prefix().
"product as p";
4728 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4729 $sql .=
", ".$this->db->prefix().
"societe_commerciaux as sc";
4732 $sql .=
" WHERE d.entity IN (".getEntity(
'mo').
")";
4733 $sql .=
" AND d.status > 0";
4735 if ($this->
id > 0) {
4736 $sql .=
" AND d.fk_product = ".((int) $this->
id);
4738 $sql .=
" AND d.fk_product > 0";
4740 if ($filteronproducttype >= 0) {
4741 $sql .=
" AND p.rowid = d.fk_product AND p.fk_product_type = ".((int) $filteronproducttype);
4744 if (!$user->hasRight(
'societe',
'client',
'voir')) {
4745 $sql .=
" AND d.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4748 $sql .=
" AND d.fk_soc = ".((int) $socid);
4750 $sql .= $morefilter;
4751 $sql .=
" GROUP BY date_format(d.date_valid,'%Y%m')";
4752 $sql .=
" ORDER BY date_format(d.date_valid,'%Y%m') DESC";
4754 return $this->
_get_stats($sql, $mode, $year);
4774 if (!is_numeric($id_pere)) {
4777 if (!is_numeric($id_fils)) {
4780 if (!is_numeric($incdec)) {
4790 $sql =
"SELECT fk_product_pere from ".$this->db->prefix().
"product_association";
4791 $sql .=
" WHERE fk_product_pere = ".((int) $id_fils).
" AND fk_product_fils = ".((int) $id_pere);
4792 if (!$this->db->query($sql)) {
4797 $sql =
"SELECT MAX(rang) as max_rank FROM ".$this->db->prefix().
"product_association";
4798 $sql .=
" WHERE fk_product_pere = ".((int) $id_pere);
4799 $resql = $this->db->query($sql);
4801 $obj = $this->db->fetch_object($resql);
4802 $rank = $obj->max_rank + 1;
4804 $sql =
"INSERT INTO ".$this->db->prefix().
"product_association(fk_product_pere,fk_product_fils,qty,incdec,rang)";
4805 $sql .=
" VALUES (".((int) $id_pere).
", ".((int) $id_fils).
", ".
price2num($qty,
'MS').
", ".((int) $incdec).
", ".((int) $rank).
")";
4806 if (! $this->db->query($sql)) {
4812 $result = $this->
call_trigger(
'PRODUCT_SUBPRODUCT_ADD', $user);
4814 $this->error = $this->db->lasterror();
4815 dol_syslog(get_class($this).
'::addSubproduct error='.$this->error, LOG_ERR);
4847 if (!is_numeric($id_pere)) {
4850 if (!is_numeric($id_fils)) {
4853 if (!is_numeric($incdec)) {
4856 if (!is_numeric($qty)) {
4860 $sql =
'UPDATE '.$this->db->prefix().
'product_association SET ';
4861 $sql .=
'qty = '.price2num($qty,
'MS');
4862 $sql .=
',incdec = '.((int) $incdec);
4863 $sql .=
' WHERE fk_product_pere = '.((int) $id_pere).
' AND fk_product_fils = '.((int) $id_fils);
4865 if (!$this->db->query($sql)) {
4871 $result = $this->
call_trigger(
'PRODUCT_SUBPRODUCT_UPDATE', $user);
4873 $this->error = $this->db->lasterror();
4874 dol_syslog(get_class($this).
'::updateSubproduct error='.$this->error, LOG_ERR);
4898 if (!is_numeric($fk_parent)) {
4901 if (!is_numeric($fk_child)) {
4905 $sql =
"DELETE FROM ".$this->db->prefix().
"product_association";
4906 $sql .=
" WHERE fk_product_pere = ".((int) $fk_parent);
4907 $sql .=
" AND fk_product_fils = ".((int) $fk_child);
4909 dol_syslog(get_class($this).
'::del_sousproduit', LOG_DEBUG);
4910 if (!$this->db->query($sql)) {
4916 $sqlrank =
"SELECT rowid, rang FROM ".$this->db->prefix().
"product_association";
4917 $sqlrank .=
" WHERE fk_product_pere = ".((int) $fk_parent);
4918 $sqlrank .=
" ORDER BY rang";
4919 $resqlrank = $this->db->query($sqlrank);
4922 while ($objrank = $this->db->fetch_object($resqlrank)) {
4924 $sql =
"UPDATE ".$this->db->prefix().
"product_association";
4925 $sql .=
" SET rang = ".((int) $cpt);
4926 $sql .=
" WHERE rowid = ".((int) $objrank->rowid);
4927 if (! $this->db->query($sql)) {
4936 $result = $this->
call_trigger(
'PRODUCT_SUBPRODUCT_DELETE', $user);
4938 $this->error = $this->db->lasterror();
4939 dol_syslog(get_class($this).
'::delSubproduct error='.$this->error, LOG_ERR);
4959 $sql =
"SELECT fk_product_pere, qty, incdec";
4960 $sql .=
" FROM ".$this->db->prefix().
"product_association";
4961 $sql .=
" WHERE fk_product_pere = ".((int) $fk_parent);
4962 $sql .=
" AND fk_product_fils = ".((int) $fk_child);
4964 $result = $this->db->query($sql);
4966 $num = $this->db->num_rows($result);
4969 $obj = $this->db->fetch_object($result);
4971 $this->is_sousproduit_qty = $obj->qty;
4972 $this->is_sousproduit_incdec = $obj->incdec;
5003 dol_syslog(get_class($this).
"::add_fournisseur id_fourn = ".$id_fourn.
" ref_fourn=".$ref_fourn.
" quantity=".$quantity, LOG_DEBUG);
5010 $sql =
"SELECT rowid, fk_product";
5011 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price";
5012 $sql .=
" WHERE fk_soc = ".((int) $id_fourn);
5013 $sql .=
" AND ref_fourn = '".$this->db->escape($ref_fourn).
"'";
5014 $sql .=
" AND fk_product <> ".((int) $this->
id);
5015 $sql .=
" AND entity IN (".getEntity(
'productsupplierprice').
")";
5017 $resql = $this->db->query($sql);
5019 $obj = $this->db->fetch_object($resql);
5022 $this->product_id_already_linked = $obj->fk_product;
5025 $this->db->free($resql);
5029 $sql =
"SELECT rowid";
5030 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price";
5031 $sql .=
" WHERE fk_soc = ".((int) $id_fourn);
5033 $sql .=
" AND ref_fourn = '".$this->db->escape($ref_fourn).
"'";
5035 $sql .=
" AND (ref_fourn = '' OR ref_fourn IS NULL)";
5037 $sql .=
" AND quantity = ".((float) $quantity);
5038 $sql .=
" AND fk_product = ".((int) $this->
id);
5039 $sql .=
" AND entity IN (".getEntity(
'productsupplierprice').
")";
5041 $resql = $this->db->query($sql);
5043 $obj = $this->db->fetch_object($resql);
5047 $sql =
"INSERT INTO ".$this->db->prefix().
"product_fournisseur_price(";
5050 $sql .=
", fk_product";
5052 $sql .=
", ref_fourn";
5053 $sql .=
", quantity";
5054 $sql .=
", fk_user";
5056 $sql .=
") VALUES (";
5057 $sql .=
"'".$this->db->idate($now).
"'";
5058 $sql .=
", ".((int)
$conf->entity);
5059 $sql .=
", ".((int) $this->
id);
5060 $sql .=
", ".((int) $id_fourn);
5061 $sql .=
", '".$this->db->escape($ref_fourn).
"'";
5062 $sql .=
", ".((float) $quantity);
5063 $sql .=
", ".((int) $user->id);
5067 if ($this->db->query($sql)) {
5068 $this->product_fourn_price_id = $this->db->last_insert_id($this->db->prefix().
"product_fournisseur_price");
5071 $this->error = $this->db->lasterror();
5076 $this->product_fourn_price_id = $obj->rowid;
5080 $this->error = $this->db->lasterror();
5099 $sql =
"SELECT DISTINCT p.fk_soc";
5100 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price as p";
5101 $sql .=
" WHERE p.fk_product = ".((int) $this->
id);
5102 $sql .=
" AND p.entity = ".((int)
$conf->entity);
5104 $result = $this->db->query($sql);
5106 $num = $this->db->num_rows($result);
5109 $obj = $this->db->fetch_object($result);
5110 $list[$i] = $obj->fk_soc;
5135 $sql =
"INSERT INTO ".$this->db->prefix().
"product_price (";
5137 $sql .=
", fk_product";
5138 $sql .=
", date_price";
5139 $sql .=
", price_level";
5141 $sql .=
", price_ttc";
5142 $sql .=
", price_min";
5143 $sql .=
", price_min_ttc";
5144 $sql .=
", price_base_type";
5145 $sql .=
", price_label";
5146 $sql .=
", default_vat_code";
5148 $sql .=
", recuperableonly";
5149 $sql .=
", localtax1_tx";
5150 $sql .=
", localtax1_type";
5151 $sql .=
", localtax2_tx";
5152 $sql .=
", localtax2_type";
5153 $sql .=
", fk_user_author";
5155 $sql .=
", price_by_qty";
5156 $sql .=
", fk_price_expression";
5157 $sql .=
", fk_multicurrency";
5158 $sql .=
", multicurrency_code";
5159 $sql .=
", multicurrency_tx";
5160 $sql .=
", multicurrency_price";
5161 $sql .=
", multicurrency_price_ttc";
5166 $sql .=
", '".$this->db->idate($now).
"'";
5167 $sql .=
", price_level";
5169 $sql .=
", price_ttc";
5170 $sql .=
", price_min";
5171 $sql .=
", price_min_ttc";
5172 $sql .=
", price_base_type";
5173 $sql .=
", price_label";
5174 $sql .=
", default_vat_code";
5176 $sql .=
", recuperableonly";
5177 $sql .=
", localtax1_tx";
5178 $sql .=
", localtax1_type";
5179 $sql .=
", localtax2_tx";
5180 $sql .=
", localtax2_type";
5181 $sql .=
", ".$user->id;
5183 $sql .=
", price_by_qty";
5184 $sql .=
", fk_price_expression";
5185 $sql .=
", fk_multicurrency";
5186 $sql .=
", multicurrency_code";
5187 $sql .=
", multicurrency_tx";
5188 $sql .=
", multicurrency_price";
5189 $sql .=
", multicurrency_price_ttc";
5190 $sql .=
" FROM ".$this->db->prefix().
"product_price ps";
5191 $sql .=
" WHERE fk_product = ".((int) $fromId);
5192 $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)";
5193 $sql .=
" ORDER BY date_price DESC";
5196 $resql = $this->db->query($sql);
5198 $this->db->rollback();
5202 $this->db->commit();
5219 $sql =
'INSERT INTO '.$this->db->prefix().
'product_association (fk_product_pere, fk_product_fils, qty, incdec)';
5220 $sql .=
" SELECT ".$toId.
", fk_product_fils, qty, incdec FROM ".$this->db->prefix().
"product_association";
5221 $sql .=
" WHERE fk_product_pere = ".((int) $fromId);
5223 dol_syslog(get_class($this).
'::clone_association', LOG_DEBUG);
5224 if (!$this->db->query($sql)) {
5225 $this->db->rollback();
5229 $this->db->commit();
5262 $sql =
"INSERT ".$this->db->prefix().
"product_fournisseur_price (";
5263 $sql .=
" datec, fk_product, fk_soc, price, quantity, fk_user, tva_tx)";
5264 $sql .=
" SELECT '".$this->db->idate($now).
"', ".((int) $toId).
", fk_soc, price, quantity, fk_user, tva_tx";
5265 $sql .=
" FROM ".$this->db->prefix().
"product_fournisseur_price";
5266 $sql .=
" WHERE fk_product = ".((int) $fromId);
5268 dol_syslog(get_class($this).
'::clone_fournisseurs', LOG_DEBUG);
5269 $resql = $this->db->query($sql);
5271 $this->db->rollback();
5274 $this->db->commit();
5292 public function fetch_prod_arbo($prod, $compl_path =
'', $multiply = 1, $level = 1, $id_parent = 0, $ignore_stock_load = 0)
5298 foreach ($prod as $id_product => $desc_pere) {
5299 if (is_array($desc_pere)) {
5300 $id = (!empty($desc_pere[0]) ? $desc_pere[0] :
'');
5301 $nb = (!empty($desc_pere[1]) ? $desc_pere[1] :
'');
5302 $type = (!empty($desc_pere[2]) ? $desc_pere[2] :
'');
5303 $label = (!empty($desc_pere[3]) ? $desc_pere[3] :
'');
5304 $incdec = (!empty($desc_pere[4]) ? $desc_pere[4] : 0);
5306 if ($multiply < 1) {
5311 if (is_null($tmpproduct)) {
5312 $tmpproduct =
new Product($this->db);
5314 $tmpproduct->fetch($id);
5316 if (empty($ignore_stock_load) && ($tmpproduct->isProduct() ||
getDolGlobalString(
'STOCK_SUPPORTS_SERVICES'))) {
5317 $tmpproduct->load_stock(
'nobatch,novirtual');
5320 $this->res[] = array(
5322 'id_parent' => $id_parent,
5323 'ref' => $tmpproduct->ref,
5325 'nb_total' => $nb * $multiply,
5326 'stock' => $tmpproduct->stock_reel,
5327 'stock_alert' => $tmpproduct->seuil_stock_alerte,
5329 'fullpath' => $compl_path.$label,
5331 'desiredstock' => $tmpproduct->desiredstock,
5333 'incdec' => $incdec,
5334 'entity' => $tmpproduct->entity
5338 if (isset($desc_pere[
'childs']) && is_array($desc_pere[
'childs'])) {
5340 $this->
fetch_prod_arbo($desc_pere[
'childs'], $compl_path.$desc_pere[3].
" -> ", $desc_pere[1] * $multiply, $level + 1, $id, $ignore_stock_load);
5358 $this->res = array();
5359 if (isset($this->sousprods) && is_array($this->sousprods)) {
5360 foreach ($this->sousprods as $prod_name => $desc_product) {
5361 if (is_array($desc_product)) {
5362 $this->
fetch_prod_arbo($desc_product,
"", $multiply, 1, $this->
id, $ignore_stock_load);
5381 $sql =
"SELECT COUNT(pa.rowid) as nb";
5382 $sql .=
" FROM ".$this->db->prefix().
"product_association as pa";
5384 $sql .=
" WHERE pa.fk_product_fils = ".((int) $this->
id).
" OR pa.fk_product_pere = ".((int) $this->
id);
5385 } elseif ($mode == -1) {
5386 $sql .=
" WHERE pa.fk_product_fils = ".((int) $this->
id);
5387 } elseif ($mode == 1) {
5388 $sql .=
" WHERE pa.fk_product_pere = ".((int) $this->
id);
5391 $resql = $this->db->query($sql);
5393 $obj = $this->db->fetch_object($resql);
5412 $sql =
"SELECT count(rowid) as nb FROM ".$this->db->prefix().
"product_attribute_combination WHERE fk_product_parent = ".((int) $this->
id);
5413 $sql .=
" AND entity IN (".getEntity(
'product').
")";
5415 $resql = $this->db->query($sql);
5417 $obj = $this->db->fetch_object($resql);
5434 if (isModEnabled(
'variants')) {
5435 $sql =
"SELECT rowid FROM ".$this->db->prefix().
"product_attribute_combination WHERE fk_product_child = ".((int) $this->
id).
" AND entity IN (".
getEntity(
'product').
")";
5437 $query = $this->db->query($sql);
5440 if (!$this->db->num_rows($query)) {
5461 $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";
5462 $sql .=
", p.tosell as status, p.tobuy as status_buy";
5463 $sql .=
" FROM ".$this->db->prefix().
"product_association as pa,";
5464 $sql .=
" ".$this->db->prefix().
"product as p";
5465 $sql .=
" WHERE p.rowid = pa.fk_product_pere";
5466 $sql .=
" AND pa.fk_product_fils = ".((int) $this->
id);
5468 $res = $this->db->query($sql);
5471 while ($record = $this->db->fetch_array($res)) {
5473 $prods[$record[
'id']] = array();
5474 $prods[$record[
'id']][
'id'] = $record[
'rowid'];
5475 $prods[$record[
'id']][
'ref'] = $record[
'ref'];
5476 $prods[$record[
'id']][
'label'] = $record[
'label'];
5477 $prods[$record[
'id']][
'qty'] = $record[
'qty'];
5478 $prods[$record[
'id']][
'incdec'] = $record[
'incdec'];
5479 $prods[$record[
'id']][
'fk_product_type'] = $record[
'fk_product_type'];
5480 $prods[$record[
'id']][
'entity'] = $record[
'entity'];
5481 $prods[$record[
'id']][
'status'] = $record[
'status'];
5482 $prods[$record[
'id']][
'status_buy'] = $record[
'status_buy'];
5501 public function getChildsArbo($id, $firstlevelonly = 0, $level = 1, $parents = array())
5503 global $alreadyfound;
5509 $sql =
"SELECT p.rowid, p.ref, p.label as label, p.fk_product_type,";
5510 $sql .=
" pa.qty as qty, pa.fk_product_fils as id, pa.incdec,";
5511 $sql .=
" pa.rowid as fk_association, pa.rang";
5512 $sql .=
" FROM ".$this->db->prefix().
"product as p,";
5513 $sql .=
" ".$this->db->prefix().
"product_association as pa";
5514 $sql .=
" WHERE p.rowid = pa.fk_product_fils";
5515 $sql .=
" AND pa.fk_product_pere = ".((int) $id);
5516 $sql .=
" AND pa.fk_product_fils <> ".((int) $id);
5517 $sql .=
" ORDER BY pa.rang";
5519 dol_syslog(get_class($this).
'::getChildsArbo id='.$id.
' level='.$level.
' parents='.(is_array($parents) ? implode(
',', $parents) : $parents), LOG_DEBUG);
5522 $alreadyfound = array($id => 1);
5529 $res = $this->db->query($sql);
5532 while ($rec = $this->db->fetch_array($res)) {
5533 if (!empty($alreadyfound[$rec[
'rowid']])) {
5534 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);
5535 if (in_array($rec[
'id'], $parents)) {
5539 $alreadyfound[$rec[
'rowid']] = 1;
5540 $prods[$rec[
'rowid']] = array(
5543 2 => $rec[
'fk_product_type'],
5544 3 => $this->db->escape($rec[
'label']),
5545 4 => $rec[
'incdec'],
5547 6 => $rec[
'fk_association'],
5552 if (empty($firstlevelonly)) {
5553 $parents[] = $rec[
'rowid'];
5554 $listofchilds = $this->
getChildsArbo($rec[
'rowid'], 0, $level + 1, $parents);
5555 foreach ($listofchilds as $keyChild => $valueChild) {
5556 $prods[$rec[
'rowid']][
'childs'][$keyChild] = $valueChild;
5580 foreach ($this->
getChildsArbo($this->
id) as $keyChild => $valueChild) {
5581 $parent[$this->label][$keyChild] = $valueChild;
5583 foreach ($parent as $key => $value) {
5584 $this->sousprods[$key] = $value;
5597 global
$conf, $langs, $user;
5599 $langs->loadLangs(array(
'products',
'other'));
5602 $nofetch = !empty($params[
'nofetch']);
5605 return [
'optimize' => $langs->trans(
"ShowProduct")];
5609 $permissiontoreadproduct = 0;
5610 if ($this->
type == self::TYPE_PRODUCT && $user->hasRight(
'product',
'read')) {
5611 $permissiontoreadproduct = 1;
5613 if ($this->
type == self::TYPE_SERVICE && $user->hasRight(
'service',
'read')) {
5614 $permissiontoreadproduct = 1;
5617 if (!empty($this->entity) && $permissiontoreadproduct) {
5618 $tmpphoto = $this->
show_photos(
'product', $conf->product->multidir_output[$this->entity], 1, 1, 0, 0, 0, 80, 0, 0, 0, 0,
'1');
5619 if ($this->nbphoto > 0) {
5620 $datas[
'photo'] =
'<div class="photointooltip floatright">'.
"\n" . $tmpphoto .
'</div>';
5625 $datas[
'picto'] =
img_picto(
'',
'product').
' <u class="paddingrightonly">'.$langs->trans(
"Product").
'</u>';
5627 $datas[
'picto'] =
img_picto(
'',
'service').
' <u class="paddingrightonly">'.$langs->trans(
"Service").
'</u>';
5629 if (isset($this->
status) && isset($this->status_buy)) {
5630 $datas[
'status'] =
' '.$this->getLibStatut(5, 0) .
' '.$this->getLibStatut(5, 1);
5633 if (!empty($this->
ref)) {
5634 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'ProductRef').
':</b> '.$this->ref;
5636 if (!empty($this->label)) {
5637 $datas[
'label'] =
'<br><b>'.$langs->trans(
'ProductLabel').
':</b> '.$this->label;
5640 if ($permissiontoreadproduct) {
5645 if (isModEnabled(
'productbatch')) {
5646 $langs->load(
"productbatch");
5647 $datas[
'batchstatus'] =
"<br><b>".$langs->trans(
"ManageLotSerial").
'</b>: '.$this->
getLibStatut(0, 2);
5650 if (isModEnabled(
'barcode')) {
5651 $datas[
'barcode'] =
'<br><b>'.$langs->trans(
'BarCode').
':</b> '.$this->barcode;
5655 if ($this->weight) {
5656 $datas[
'weight'] =
"<br><b>".$langs->trans(
"Weight").
'</b>: '.$this->weight.
' '.
measuringUnitString(0,
"weight", $this->weight_units);
5659 if ($this->length) {
5660 $labelsize .= ($labelsize ?
" - " :
"").
"<b>".$langs->trans(
"Length").
'</b>: '.$this->length.
' '.
measuringUnitString(0,
'size', $this->length_units);
5663 $labelsize .= ($labelsize ?
" - " :
"").
"<b>".$langs->trans(
"Width").
'</b>: '.$this->width.
' '.
measuringUnitString(0,
'size', $this->width_units);
5665 if ($this->height) {
5666 $labelsize .= ($labelsize ?
" - " :
"").
"<b>".$langs->trans(
"Height").
'</b>: '.$this->height.
' '.
measuringUnitString(0,
'size', $this->height_units);
5669 $datas[
'size'] =
"<br>".$labelsize;
5672 $labelsurfacevolume =
"";
5673 if ($this->surface) {
5674 $labelsurfacevolume .= ($labelsurfacevolume ?
" - " :
"").
"<b>".$langs->trans(
"Surface").
'</b>: '.$this->surface.
' '.
measuringUnitString(0,
'surface', $this->surface_units);
5676 if ($this->volume) {
5677 $labelsurfacevolume .= ($labelsurfacevolume ?
" - " :
"").
"<b>".$langs->trans(
"Volume").
'</b>: '.$this->volume.
' '.
measuringUnitString(0,
'volume', $this->volume_units);
5679 if ($labelsurfacevolume) {
5680 $datas[
'surface'] =
"<br>" . $labelsurfacevolume;
5683 if ($this->
isService() && !empty($this->duration_value)) {
5685 $datas[
'duration'] =
'<br><b>'.$langs->trans(
"Duration").
':</b> '.$this->duration_value;
5686 if ($this->duration_value > 1) {
5687 $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"));
5688 } elseif ($this->duration_value > 0) {
5689 $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"));
5691 $datas[
'duration'] .= (!empty($this->duration_unit) && isset($dur[$this->duration_unit]) ?
" ".$langs->trans($dur[$this->duration_unit]) :
'');
5693 if (empty($user->socid)) {
5694 if (!empty($this->pmp) && $this->pmp) {
5695 $datas[
'pmp'] =
"<br><b>".$langs->trans(
"PMPValue").
'</b>: '.
price($this->pmp, 0,
'', 1, -1, -1,
$conf->currency);
5698 if (isModEnabled(
'accounting')) {
5699 if ($this->
status && isset($this->accountancy_code_sell)) {
5700 include_once DOL_DOCUMENT_ROOT.
'/core/lib/accounting.lib.php';
5701 $selllabel =
'<br>';
5702 $selllabel .=
'<br><b>'.$langs->trans(
'ProductAccountancySellCode').
':</b> '.
length_accountg($this->accountancy_code_sell);
5703 $selllabel .=
'<br><b>'.$langs->trans(
'ProductAccountancySellIntraCode').
':</b> '.
length_accountg($this->accountancy_code_sell_intra);
5704 $selllabel .=
'<br><b>'.$langs->trans(
'ProductAccountancySellExportCode').
':</b> '.
length_accountg($this->accountancy_code_sell_export);
5705 $datas[
'accountancysell'] = $selllabel;
5707 if ($this->status_buy && isset($this->accountancy_code_buy)) {
5708 include_once DOL_DOCUMENT_ROOT.
'/core/lib/accounting.lib.php';
5710 if (empty($this->
status)) {
5711 $buylabel .=
'<br>';
5713 $buylabel .=
'<br><b>'.$langs->trans(
'ProductAccountancyBuyCode').
':</b> '.
length_accountg($this->accountancy_code_buy);
5714 $buylabel .=
'<br><b>'.$langs->trans(
'ProductAccountancyBuyIntraCode').
':</b> '.
length_accountg($this->accountancy_code_buy_intra);
5715 $buylabel .=
'<br><b>'.$langs->trans(
'ProductAccountancyBuyExportCode').
':</b> '.
length_accountg($this->accountancy_code_buy_export);
5716 $datas[
'accountancybuy'] = $buylabel;
5721 if (isModEnabled(
'category') && !$nofetch) {
5722 require_once DOL_DOCUMENT_ROOT .
'/categories/class/categorie.class.php';
5723 $form =
new Form($this->db);
5724 $datas[
'categories'] =
'<br>' . $form->showCategories($this->
id, Categorie::TYPE_PRODUCT, 1);
5744 public function getNomUrl($withpicto = 0, $option =
'', $maxlength = 0, $save_lastsearch_value = -1, $notooltip = 0, $morecss =
'', $add_label = 0, $sep =
' - ')
5746 global $langs, $hookmanager;
5748 include_once DOL_DOCUMENT_ROOT.
'/core/lib/product.lib.php';
5752 $newref = $this->ref;
5754 $newref =
dol_trunc($newref, $maxlength,
'middle');
5758 'objecttype' => ($this->
type == 1 ?
'service' :
'product'),
5759 'option' => $option,
5762 $classfortooltip =
'classfortooltip';
5765 $classfortooltip =
'classforajaxtooltip';
5766 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
5773 if (empty($notooltip)) {
5775 $label = $langs->trans(
"ShowProduct");
5776 $linkclose .=
' alt="'.dol_escape_htmltag($label, 1, 1).
'"';
5778 $linkclose .= ($label ?
' title="'.dol_escape_htmltag($label, 1, 1).
'"' :
' title="tocomplete"');
5779 $linkclose .= $dataparams.
' class="nowraponall '.$classfortooltip.($morecss ?
' '.$morecss :
'').
'"';
5781 $linkclose =
' class="nowraponall'.($morecss ?
' '.$morecss :
'').
'"';
5784 if ($option ==
'supplier' || $option ==
'category') {
5785 $url = DOL_URL_ROOT.
'/product/price_suppliers.php?id='.$this->id;
5786 } elseif ($option ==
'stock') {
5787 $url = DOL_URL_ROOT.
'/product/stock/product.php?id='.$this->id;
5788 } elseif ($option ==
'composition') {
5789 $url = DOL_URL_ROOT.
'/product/composition/card.php?id='.$this->id;
5791 $url = DOL_URL_ROOT.
'/product/card.php?id='.$this->id;
5794 if ($option !==
'nolink') {
5796 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
5797 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
5798 $add_save_lastsearch_values = 1;
5800 if ($add_save_lastsearch_values) {
5801 $url .=
'&save_lastsearch_values=1';
5805 $linkstart =
'<a href="'.$url.
'"';
5806 $linkstart .= $linkclose.
'>';
5809 $result .= $linkstart;
5812 $result .= (
img_object(($notooltip ?
'' : $label),
'product',
'class="paddingright"', 0, 0, $notooltip ? 0 : 1));
5815 $result .= (
img_object(($notooltip ?
'' : $label),
'service',
'class="paddingright"', 0, 0, $notooltip ? 0 : 1));
5818 $result .=
'<span class="aaa">'.dol_escape_htmltag($newref).
'</span>';
5819 $result .= $linkend;
5820 if ($withpicto != 2) {
5821 $result .= (($add_label && $this->label) ? $sep.dol_trunc($this->label, ($add_label > 1 ? $add_label : 0)) :
'');
5825 $hookmanager->initHooks(array(
'productdao'));
5826 $parameters = array(
'id' => $this->
id,
'getnomurl' => &$result,
'label' => &$label);
5827 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
5829 $result = $hookmanager->resPrint;
5831 $result .= $hookmanager->resPrint;
5848 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
5852 $langs->load(
"products");
5853 $outputlangs->load(
"products");
5860 $modelpath =
"core/modules/product/doc/";
5862 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
5878 return $this->
LibStatut($this->status_buy, $mode, $type);
5880 return $this->
LibStatut($this->status_batch, $mode, $type);
5883 return $this->
LibStatut($this->status_buy, $mode, $type);
5901 $labelStatus = $labelStatusShort =
'';
5903 $langs->load(
'products');
5904 if (isModEnabled(
'productbatch')) {
5905 $langs->load(
"productbatch");
5911 $label = ($status == 0 ? $langs->transnoentitiesnoconv(
'ProductStatusNotOnBatch') : ($status == 1 ? $langs->transnoentitiesnoconv(
'ProductStatusOnBatch') : $langs->transnoentitiesnoconv(
'ProductStatusOnSerial')));
5914 $label = ($status == 0 ? $langs->transnoentitiesnoconv(
'ProductStatusNotOnBatchShort') : ($status == 1 ? $langs->transnoentitiesnoconv(
'ProductStatusOnBatchShort') : $langs->transnoentitiesnoconv(
'ProductStatusOnSerialShort')));
5919 return dolGetStatus($langs->transnoentitiesnoconv(
'ProductStatusNotOnBatch'),
'',
'', empty($status) ?
'status5' :
'status4', 3,
'dot');
5925 return dolGetStatus($langs->transnoentitiesnoconv(
'Unknown'));
5929 $statuttrans = empty($status) ?
'status5' :
'status4';
5934 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusNotOnSellShort');
5935 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusNotOnSell');
5936 } elseif ($type == 1) {
5937 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusNotOnBuyShort');
5938 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusNotOnBuy');
5939 } elseif ($type == 2) {
5940 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusNotOnBatch');
5941 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusNotOnBatchShort');
5943 } elseif ($status == 1) {
5946 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusOnSellShort');
5947 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusOnSell');
5948 } elseif ($type == 1) {
5949 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusOnBuyShort');
5950 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusOnBuy');
5951 } elseif ($type == 2) {
5952 $labelStatus = ($status == 1 ? $langs->transnoentitiesnoconv(
'ProductStatusOnBatch') : $langs->transnoentitiesnoconv(
'ProductStatusOnSerial'));
5953 $labelStatusShort = ($status == 1 ? $langs->transnoentitiesnoconv(
'ProductStatusOnBatchShort') : $langs->transnoentitiesnoconv(
'ProductStatusOnSerialShort'));
5955 } elseif ($type == 2 && $status == 2) {
5956 $labelStatus = $langs->transnoentitiesnoconv(
'ProductStatusOnSerial');
5957 $labelStatusShort = $langs->transnoentitiesnoconv(
'ProductStatusOnSerialShort');
5961 return dolGetStatus($langs->transnoentitiesnoconv(
'Unknown'),
'',
'',
'status0', 0);
5963 return dolGetStatus($labelStatus, $labelStatusShort,
'', $statuttrans, $mode);
5977 $langs->load(
'products');
5980 if (isset($this->finished) && $this->finished >= 0) {
5981 $sql =
"SELECT label, code FROM ".$this->db->prefix().
"c_product_nature where code = ".((int) $this->finished).
" AND active=1";
5982 $resql = $this->db->query($sql);
5984 $this->error = $this->db->error().
' sql='.$sql;
5985 dol_syslog(__METHOD__.
' Error '.$this->error, LOG_ERR);
5987 } elseif ($this->db->num_rows($resql) > 0 && $res = $this->db->fetch_array($resql)) {
5988 $label = $langs->trans($res[
'label']);
5990 $this->db->free($resql);
6014 public function correct_stock($user, $id_entrepot, $nbpiece, $movement, $label =
'', $price = 0, $inventorycode =
'', $origin_element =
'', $origin_id =
null, $disablestockchangeforsubproduct = 0, $extrafields =
null)
6020 include_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
6026 $nbpiece = abs($nbpiece);
6029 $op[0] =
"+".trim((
string) $nbpiece);
6030 $op[1] =
"-".trim((
string) $nbpiece);
6033 $movementstock->setOrigin($origin_element, $origin_id);
6034 $result = $movementstock->_create($user, $this->
id, $id_entrepot, $op[$movement], $movement, $price, $label, $inventorycode,
'',
'',
'',
'',
false, 0, $disablestockchangeforsubproduct);
6038 $array_options = $extrafields->getOptionalsFromPost(
'stock_mouvement');
6039 $movementstock->array_options = $array_options;
6040 $movementstock->insertExtraFields();
6042 $this->db->commit();
6045 $this->error = $movementstock->error;
6046 $this->errors = $movementstock->errors;
6048 $this->db->rollback();
6077 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)
6083 include_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
6089 $nbpiece = abs($nbpiece);
6093 $op[0] =
"+".trim((
string) $nbpiece);
6094 $op[1] =
"-".trim((
string) $nbpiece);
6097 $movementstock->setOrigin($origin_element, $origin_id);
6098 $result = $movementstock->_create($user, $this->
id, $id_entrepot, $op[$movement], $movement, $price, $label, $inventorycode,
'', $dlc, $dluo, $lot,
false, 0, $disablestockchangeforsubproduct, 0, $force_update_batch);
6102 $array_options = $extrafields->getOptionalsFromPost(
'stock_mouvement');
6103 $movementstock->array_options = $array_options;
6104 $movementstock->insertExtraFields();
6106 $this->db->commit();
6109 $this->error = $movementstock->error;
6110 $this->errors = $movementstock->errors;
6112 $this->db->rollback();
6132 public function load_stock($option =
'', $includedraftpoforvirtual =
null, $dateofvirtualstock =
null)
6135 $this->stock_reel = 0;
6136 $this->stock_warehouse = array();
6137 $this->stock_theorique = 0;
6140 $warehouseStatus = array();
6141 if (preg_match(
'/warehouseclosed/', $option)) {
6144 if (preg_match(
'/warehouseopen/', $option)) {
6147 if (preg_match(
'/warehouseinternal/', $option)) {
6155 $sql =
"SELECT ps.rowid, ps.reel, ps.fk_entrepot";
6156 $sql .=
" FROM ".$this->db->prefix().
"product_stock as ps";
6157 $sql .=
", ".$this->db->prefix().
"entrepot as w";
6158 $sql .=
" WHERE w.entity IN (".getEntity(
'stock').
")";
6159 $sql .=
" AND w.rowid = ps.fk_entrepot";
6160 $sql .=
" AND ps.fk_product = ".((int) $this->
id);
6161 if (count($warehouseStatus)) {
6162 $sql .=
" AND w.statut IN (".$this->db->sanitize(implode(
',', $warehouseStatus)).
")";
6165 $sql .=
" ORDER BY ps.reel ".(getDolGlobalString(
'DO_NOT_TRY_TO_DEFRAGMENT_STOCKS_WAREHOUSE') ?
'DESC' :
'ASC');
6167 dol_syslog(get_class($this).
"::load_stock", LOG_DEBUG);
6168 $result = $this->db->query($sql);
6170 $num = $this->db->num_rows($result);
6174 $row = $this->db->fetch_object($result);
6175 $this->stock_warehouse[$row->fk_entrepot] =
new stdClass();
6176 $this->stock_warehouse[$row->fk_entrepot]->real = $row->reel;
6177 $this->stock_warehouse[$row->fk_entrepot]->id = $row->rowid;
6178 if ((!preg_match(
'/nobatch/', $option)) && $this->
hasbatch()) {
6179 $this->stock_warehouse[$row->fk_entrepot]->detail_batch =
Productbatch::findAll($this->db, $row->rowid, 1, $this->id);
6181 $this->stock_reel += $row->reel;
6184 $this->stock_reel = (float)
price2num($this->stock_reel,
'MS');
6186 $this->db->free($result);
6188 if (!preg_match(
'/novirtual/', $option)) {
6194 $this->error = $this->db->lasterror();
6213 global $hookmanager, $action;
6215 $stock_commande_client = 0;
6216 $stock_commande_fournisseur = 0;
6217 $stock_sending_client = 0;
6218 $stock_reception_fournisseur = 0;
6219 $stock_inproduction = 0;
6223 if (isModEnabled(
'order')) {
6228 $stock_commande_client = $this->stats_commande[
'qty'];
6230 if (isModEnabled(
"shipping")) {
6231 require_once DOL_DOCUMENT_ROOT.
'/expedition/class/expedition.class.php';
6232 $filterShipmentStatus =
'';
6242 $stock_sending_client = $this->stats_expedition[
'qty'];
6245 if (isModEnabled(
"supplier_order")) {
6246 $filterStatus =
getDolGlobalString(
'SUPPLIER_ORDER_STATUS_FOR_VIRTUAL_STOCK',
'3,4');
6247 if (isset($includedraftpoforvirtual)) {
6248 $filterStatus =
'0,1,2,'.$filterStatus;
6254 $stock_commande_fournisseur = $this->stats_commande_fournisseur[
'qty'];
6257 if (isModEnabled(
"supplier_order") || isModEnabled(
"supplier_invoice")) {
6258 $filterStatus =
'4';
6259 if (isset($includedraftpoforvirtual)) {
6260 $filterStatus =
'0,'.$filterStatus;
6266 $stock_reception_fournisseur = $this->stats_reception[
'qty'];
6269 if (isModEnabled(
'mrp')) {
6274 $stock_inproduction = $this->stats_mrptoproduce[
'qty'] - $this->stats_mrptoconsume[
'qty'];
6277 $this->stock_theorique = $this->stock_reel + $stock_inproduction;
6281 $this->stock_theorique -= ($stock_commande_client - $stock_sending_client);
6283 $this->stock_theorique += 0;
6285 $this->stock_theorique -= $stock_commande_client;
6289 $this->stock_theorique += ($stock_commande_fournisseur - $stock_reception_fournisseur);
6291 $this->stock_theorique += ($stock_commande_fournisseur - $stock_reception_fournisseur);
6293 $this->stock_theorique -= $stock_reception_fournisseur;
6295 $this->stock_theorique += ($stock_commande_fournisseur - $stock_reception_fournisseur);
6298 $parameters = array(
'id' => $this->
id,
'includedraftpoforvirtual' => $includedraftpoforvirtual);
6300 $reshook = $hookmanager->executeHooks(
'loadvirtualstock', $parameters, $this, $action);
6302 $this->stock_theorique = $hookmanager->resArray[
'stock_theorique'];
6303 } elseif ($reshook == 0 && isset($hookmanager->resArray[
'stock_stats_hook'])) {
6304 $this->stock_theorique += $hookmanager->resArray[
'stock_stats_hook'];
6308 if (!empty($this->stock_warehouse) &&
getDolGlobalString(
'STOCK_ALLOW_VIRTUAL_STOCK_PER_WAREHOUSE')) {
6309 foreach ($this->stock_warehouse as $warehouseid => $stockwarehouse) {
6310 if (isModEnabled(
'mrp')) {
6317 if ($this->fk_default_warehouse == $warehouseid) {
6318 $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']);
6320 $this->stock_warehouse[$warehouseid]->virtual = $this->stock_warehouse[$warehouseid]->real + $this->stock_warehouse[$warehouseid]->stats_mrptoproduce[
'qty'];
6340 $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";
6341 $sql .=
" WHERE pb.fk_product_stock = ps.rowid AND ps.fk_product = ".((int) $this->
id).
" AND pb.batch = '".$this->db->escape($batch).
"'";
6342 $sql .=
" GROUP BY pb.batch, pb.eatby, pb.sellby";
6343 dol_syslog(get_class($this).
"::loadBatchInfo load first entry found for lot/serial = ".$batch, LOG_DEBUG);
6344 $resql = $this->db->query($sql);
6346 $num = $this->db->num_rows($resql);
6349 $obj = $this->db->fetch_object($resql);
6350 $result[] = array(
'batch' => $batch,
'eatby' => $this->db->jdate($obj->eatby),
'sellby' => $this->db->jdate($obj->sellby),
'qty' => $obj->qty);
6356 $this->db->rollback();
6373 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6379 $dir .=
'/'.get_exdir($this->
id, 2, 0, 0, $this,
'product').$this->id.
"/photos";
6381 $dir .=
'/'.get_exdir(0, 0, 0, 0, $this,
'product').dol_sanitizeFileName($this->
ref);
6386 $dir_osencoded = $dir;
6388 if (is_dir($dir_osencoded)) {
6389 $originImage = $dir.
'/'.$file[
'name'];
6400 if (is_numeric($result) && $result > 0) {
6417 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6418 include_once DOL_DOCUMENT_ROOT.
'/core/lib/images.lib.php';
6422 $dir .=
'/'.get_exdir($this->
id, 2, 0, 0, $this,
'product').$this->id.
"/photos/";
6424 $dir .=
'/'.get_exdir(0, 0, 0, 0, $this,
'product');
6428 if (file_exists($dir_osencoded)) {
6429 $handle = opendir($dir_osencoded);
6430 if (is_resource($handle)) {
6431 while (($file = readdir($handle)) !==
false) {
6433 $file = mb_convert_encoding($file,
'UTF-8',
'ISO-8859-1');
6456 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6457 include_once DOL_DOCUMENT_ROOT.
'/core/lib/images.lib.php';
6463 $handle = @opendir($dir_osencoded);
6464 if (is_resource($handle)) {
6465 while (($file = readdir($handle)) !==
false) {
6467 $file = mb_convert_encoding($file,
'UTF-8',
'ISO-8859-1');
6474 $photo_vignette =
'';
6476 if (preg_match(
'/('.$this->regeximgext.
')$/i', $photo, $regs)) {
6477 $photo_vignette = preg_replace(
'/'.$regs[0].
'/i',
'', $photo).
'_small'.$regs[0];
6480 $dirthumb = $dir.
'thumbs/';
6484 $obj[
'photo'] = $photo;
6485 if ($photo_vignette &&
dol_is_file($dirthumb.$photo_vignette)) {
6486 $obj[
'photo_vignette'] =
'thumbs/'.$photo_vignette;
6488 $obj[
'photo_vignette'] =
"";
6491 $tabobj[$nbphoto - 1] = $obj;
6494 if ($nbmax && $nbphoto >= $nbmax) {
6516 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
6517 include_once DOL_DOCUMENT_ROOT.
'/core/lib/images.lib.php';
6519 $dir = dirname($file).
'/';
6520 $dirthumb = $dir.
'/thumbs/';
6521 $filename = preg_replace(
'/'.preg_quote($dir,
'/').
'/i',
'', $file);
6527 if (preg_match(
'/('.$this->regeximgext.
')$/i', $filename, $regs)) {
6528 $photo_vignette = preg_replace(
'/'.$regs[0].
'/i',
'', $filename).
'_small'.$regs[0];
6529 if (file_exists(
dol_osencode($dirthumb.$photo_vignette))) {
6533 $photo_vignette = preg_replace(
'/'.$regs[0].
'/i',
'', $filename).
'_mini'.$regs[0];
6534 if (file_exists(
dol_osencode($dirthumb.$photo_vignette))) {
6551 $infoImg = getimagesize($file_osencoded);
6552 $this->imgWidth = $infoImg[0];
6553 $this->imgHeight = $infoImg[1];
6563 global $hookmanager;
6565 $this->nb = array();
6567 $sql =
"SELECT count(p.rowid) as nb, fk_product_type";
6568 $sql .=
" FROM ".$this->db->prefix().
"product as p";
6569 $sql .=
' WHERE p.entity IN ('.getEntity($this->element, 1).
')';
6571 if (is_object($hookmanager)) {
6572 $parameters = array();
6573 $reshook = $hookmanager->executeHooks(
'printFieldListWhere', $parameters, $this);
6574 $sql .= $hookmanager->resPrint;
6576 $sql .=
' GROUP BY fk_product_type';
6578 $resql = $this->db->query($sql);
6580 while ($obj = $this->db->fetch_object($resql)) {
6581 if ($obj->fk_product_type == 1) {
6582 $this->nb[
"services"] = $obj->nb;
6584 $this->nb[
"products"] = $obj->nb;
6587 $this->db->free($resql);
6591 $this->error = $this->db->error();
6633 return $this->mandatory_period == 1;
6643 return $this->status_batch > 0;
6663 $dirsociete = array_merge(array(
'/core/modules/barcode/'),
$conf->modules_parts[
'barcode']);
6664 foreach ($dirsociete as $dirroot) {
6672 '@phan-var-force ModeleNumRefBarCode $mod';
6674 $result = $mod->getNextValue(
$object, $type);
6676 dol_syslog(get_class($this).
"::get_barcode barcode=".$result.
" module=".$var);
6693 $this->specimen = 1;
6695 $this->
ref =
'PRODUCT_SPEC';
6696 $this->label =
'PRODUCT SPECIMEN';
6697 $this->
description =
'This is description of this product specimen that was created the '.dol_print_date($now,
'dayhourlog').
'.';
6698 $this->specimen = 1;
6699 $this->country_id = 1;
6701 $this->status_buy = 1;
6703 $this->sell_or_eat_by_mandatory = 0;
6704 $this->note_private =
'This is a comment (private)';
6705 $this->note_public =
'This is a comment (public)';
6706 $this->date_creation = $now;
6707 $this->date_modification = $now;
6710 $this->weight_units = 3;
6713 $this->length_units = 1;
6715 $this->width_units = 0;
6716 $this->height =
null;
6717 $this->height_units =
null;
6719 $this->surface = 30;
6720 $this->surface_units = 0;
6721 $this->volume = 300;
6722 $this->volume_units = 0;
6724 $this->barcode = -1;
6739 if (!$this->fk_unit) {
6743 $langs->load(
'products');
6745 $label_type =
'label';
6746 if ($type ==
'short') {
6747 $label_type =
'short_label';
6750 $sql =
"SELECT ".$label_type.
", code from ".$this->db->prefix().
"c_units where rowid = ".((int) $this->fk_unit);
6752 $resql = $this->db->query($sql);
6754 $this->error = $this->db->error();
6755 dol_syslog(get_class($this).
"::getLabelOfUnit Error ".$this->error, LOG_ERR);
6757 } elseif ($this->db->num_rows($resql) > 0 && $res = $this->db->fetch_array($resql)) {
6758 $label = ($label_type ==
'short_label' ? $res[$label_type] :
'unit'.$res[
'code']);
6760 $this->db->free($resql);
6774 $maxpricesupplier = 0;
6777 include_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
6779 $product_fourn_list = $product_fourn->list_product_fournisseur_price($this->
id,
'',
'');
6781 if (is_array($product_fourn_list) && count($product_fourn_list) > 0) {
6782 foreach ($product_fourn_list as $productfourn) {
6783 if ($productfourn->fourn_unitprice > $maxpricesupplier) {
6784 $maxpricesupplier = $productfourn->fourn_unitprice;
6792 return $maxpricesupplier;
6808 require_once DOL_DOCUMENT_ROOT.
'/categories/class/categorie.class.php';
6809 return parent::setCategoriesCommon($categories, Categorie::TYPE_PRODUCT);
6823 'product_customer_price',
6824 'product_customer_price_log'
6843 $sql =
"SELECT rowid, level, fk_level, var_percent, var_min_percent FROM ".$this->db->prefix().
"product_pricerules";
6844 $query = $this->db->query($sql);
6848 while ($result = $this->db->fetch_object($query)) {
6849 $rules[$result->level] = $result;
6858 for ($i = 1; $i <= $nbofproducts; $i++) {
6859 $price = $baseprice;
6860 $price_min = $baseprice;
6864 if ($i > 1 && isset($rules[$i]->var_percent) && $rules[$i]->var_percent) {
6865 $price = $prices[$rules[$i]->fk_level] * (1 + ($rules[$i]->var_percent / 100));
6868 $prices[$i] = $price;
6871 if (isset($rules[$i]->var_min_percent) && $rules[$i]->var_min_percent) {
6872 $price_min = $price * (1 - ($rules[$i]->var_min_percent / 100));
6876 $check_amount = (($price == $this->multiprices[$i]) && ($price_min == $this->multiprices_min[$i]));
6877 $check_type = ($baseprice == $this->multiprices_base_type[$i]);
6879 if ($check_amount && $check_type) {
6883 if ($this->
updatePrice($price, $price_type, $user, $price_vat, $price_min, $i, $npr, $psq, 1) < 0) {
6901 return $user->rights->produit;
6903 return $user->rights->service;
6915 $sql =
"SELECT p.rowid, p.ref, p.datec as date_creation, p.tms as date_modification,";
6916 $sql .=
" p.fk_user_author, p.fk_user_modif";
6917 $sql .=
" FROM ".$this->db->prefix().$this->table_element.
" as p";
6918 $sql .=
" WHERE p.rowid = ".((int) $id);
6920 $result = $this->db->query($sql);
6922 if ($this->db->num_rows($result)) {
6923 $obj = $this->db->fetch_object($result);
6925 $this->
id = $obj->rowid;
6926 $this->
ref = $obj->ref;
6928 $this->user_creation_id = $obj->fk_user_author;
6929 $this->user_modification_id = $obj->fk_user_modif;
6931 $this->date_creation = $this->db->jdate($obj->date_creation);
6932 $this->date_modification = $this->db->jdate($obj->date_modification);
6935 $this->db->free($result);
6949 if (empty($this->duration_value)) {
6950 $this->errors[] =
'ErrorDurationForServiceNotDefinedCantCalculateHourlyPrice';
6953 if ($this->duration_unit ==
's') {
6954 $prodDurationHours = 1. / 3600;
6955 } elseif ($this->duration_unit ==
'i' || $this->duration_unit ==
'mn' || $this->duration_unit ==
'min') {
6956 $prodDurationHours = 1. / 60;
6957 } elseif ($this->duration_unit ==
'h') {
6958 $prodDurationHours = 1.;
6959 } elseif ($this->duration_unit ==
'd') {
6960 $prodDurationHours = 24.;
6961 } elseif ($this->duration_unit ==
'w') {
6962 $prodDurationHours = 24. * 7;
6963 } elseif ($this->duration_unit ==
'm') {
6964 $prodDurationHours = 24. * 30;
6965 } elseif ($this->duration_unit ==
'y') {
6966 $prodDurationHours = 24. * 365;
6968 $prodDurationHours = 0.0;
6970 $prodDurationHours *= $this->duration_value;
6972 return $prodDurationHours;
6985 global $langs,
$conf;
6987 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
6989 $return =
'<div class="box-flex-item box-flex-grow-zero">';
6990 $return .=
'<div class="info-box info-box-sm">';
6991 $return .=
'<div class="info-box-img">';
6994 $label .= $this->
show_photos(
'product', $conf->product->multidir_output[$this->entity], 1, 1, 0, 0, 0, 120, 160, 0, 0, 0,
'',
'photoref photokanban');
7004 $return .=
'</div>';
7005 $return .=
'<div class="info-box-content">';
7006 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this,
'getNomUrl') ? $this->
getNomUrl() : $this->ref).
'</span>';
7007 if ($selected >= 0) {
7008 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
7010 if (property_exists($this,
'label')) {
7011 $return .=
'<br><span class="info-box-label opacitymedium inline-block tdoverflowmax150 valignmiddle" title="'.dol_escape_htmltag($this->label).
'">'.
dol_escape_htmltag($this->label).
'</span>';
7013 if (property_exists($this,
'price') && property_exists($this,
'price_ttc')) {
7014 if ($this->price_base_type ==
'TTC') {
7015 $return .=
'<br><span class="info-box-status amount">'.price($this->price_ttc).
' '.$langs->trans(
"TTC").
'</span>';
7018 $return .=
'<br><span class="info-box-status amount">'.price($this->
price).
' '.$langs->trans(
"HT").
'</span>';
7023 if (property_exists($this,
'stock_reel') && $this->
isProduct()) {
7024 $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>';
7027 if (method_exists($this,
'getLibStatut')) {
7029 $return .=
'<br><div class="info-box-status inline-block valignmiddle">'.$this->getLibStatut(3, 1).
' '.$this->
getLibStatut(3, 0).
'</div>';
7031 $return .=
'<div class="info-box-status inline-block valignmiddle marginleftonly paddingleft">'.$this->getLibStatut(3, 1).
' '.$this->
getLibStatut(3, 0).
'</div>';
7034 $return .=
'</div>';
7035 $return .=
'</div>';
7036 $return .=
'</div>';
7049 if (!is_numeric($limit)) {
7053 $sql =
"SELECT p.rowid, p.ref, p.label, p.description, p.entity, ef.filename
7054 FROM ".MAIN_DB_PREFIX.
"product AS p
7055 JOIN ".MAIN_DB_PREFIX.
"ecm_files AS ef ON p.rowid = ef.src_object_id
7056 WHERE ef.entity IN (".
getEntity(
'product').
")
7057 AND (ef.filename LIKE '%.png' OR ef.filename LIKE '%.jpeg' OR ef.filename LIKE '%.svg')
7058 GROUP BY p.rowid, p.ref, p.label, p.description, p.entity, ef.filename
7059 ORDER BY p.datec ASC
7060 LIMIT " . ((int) $limit);
7062 $resql = $this->db->query($sql);
7063 $products = array();
7066 while ($obj = $this->db->fetch_object($resql)) {
7067 $products[] = array(
7068 'rowid' => $obj->rowid,
7070 'label' => $obj->label,
7071 'description' => $obj->description,
7072 'entity' => $obj->entity,
7073 'filename' => $obj->filename
7079 if (empty($products)) {
7092 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_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0, $indexdatabase=1, $nolog=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories)
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disablevirusscan=0, $uploaderrorcode=0, $nohook=0, $varfiles='addedfile', $upload_dir='')
Check validity of a file upload from an GUI page, and move it to its final destination.
dol_is_file($pathoffile)
Return if path is a file.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dolGetFirstLineOfText($text, $nboflines=1, $charset='UTF-8')
Return first line of text.
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_string_nospecial($str, $newstr='_', $badcharstoreplace='', $badcharstoremove='', $keepspaces=0)
Clean a string from all punctuation characters to use it as a ref or login.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
if(!function_exists( 'dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
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