24require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/entrepot.class.php';
43 public $cache_warehouses = array();
44 public $cache_lot = array();
45 public $cache_workstations = array();
76 public function loadWarehouses($fk_product = 0, $batch =
'', $status =
'', $sumStock =
true, $exclude = array(), $stockMin =
false, $orderBy =
'e.ref')
80 if (empty($fk_product) && count($this->cache_warehouses)) {
84 $warehouseStatus = array();
86 if (preg_match(
'/warehouseclosed/', $status)) {
89 if (preg_match(
'/warehouseopen/', $status)) {
92 if (preg_match(
'/warehouseinternal/', $status)) {
96 $sql =
"SELECT e.rowid, e.ref as label, e.description, e.fk_parent";
97 if (!empty($fk_product) && $fk_product > 0) {
99 $sql .=
", pb.qty as stock";
101 $sql .=
", ps.reel as stock";
103 } elseif ($sumStock) {
104 $sql .=
", sum(ps.reel) as stock";
106 $sql .=
" FROM ".$this->db->prefix().
"entrepot as e";
107 $sql .=
" LEFT JOIN ".$this->db->prefix().
"product_stock as ps on ps.fk_entrepot = e.rowid";
108 if (!empty($fk_product) && $fk_product > 0) {
109 $sql .=
" AND ps.fk_product = ".((int) $fk_product);
110 if (!empty($batch)) {
111 $sql .=
" LEFT JOIN ".$this->db->prefix().
"product_batch as pb on pb.fk_product_stock = ps.rowid AND pb.batch = '".$this->db->escape($batch).
"'";
114 $sql .=
" WHERE e.entity IN (".getEntity(
'stock').
")";
115 if (count($warehouseStatus)) {
116 $sql .=
" AND e.statut IN (".$this->db->sanitize(implode(
',', $warehouseStatus)).
")";
118 $sql .=
" AND e.statut = 1";
121 if (is_array($exclude) && !empty($exclude)) {
122 $sql .=
' AND e.rowid NOT IN('.$this->db->sanitize(implode(
',', $exclude)).
')';
126 if ($stockMin !==
false) {
127 if (!empty($fk_product) && $fk_product > 0) {
128 if (!empty($batch)) {
129 $sql .=
" AND pb.qty > ".((float) $stockMin);
131 $sql .=
" AND ps.reel > ".((float) $stockMin);
136 if ($sumStock && empty($fk_product)) {
137 $sql .=
" GROUP BY e.rowid, e.ref, e.description, e.fk_parent";
140 if ($stockMin !==
false) {
141 $sql .=
" HAVING sum(ps.reel) > ".((float) $stockMin);
144 $sql .=
" ORDER BY ".$orderBy;
146 dol_syslog(get_class($this).
'::loadWarehouses', LOG_DEBUG);
147 $resql = $this->db->query($sql);
149 $num = $this->db->num_rows($resql);
152 $obj = $this->db->fetch_object($resql);
156 $this->cache_warehouses[$obj->rowid][
'id'] = $obj->rowid;
157 $this->cache_warehouses[$obj->rowid][
'label'] = $obj->label;
158 $this->cache_warehouses[$obj->rowid][
'parent_id'] = $obj->fk_parent;
159 $this->cache_warehouses[$obj->rowid][
'description'] = $obj->description;
160 $this->cache_warehouses[$obj->rowid][
'stock'] = $obj->stock;
165 foreach ($this->cache_warehouses as $obj_rowid => $tab) {
166 $this->cache_warehouses[$obj_rowid][
'full_label'] = $this->
get_parent_path($tab);
188 global $conf, $langs;
190 if (empty($fk_product) && count($this->cache_workstations)) {
194 $sql =
"SELECT w.rowid, w.ref as ref, w.label as label, w.type, w.nb_operators_required,w.thm_operator_estimated,w.thm_machine_estimated";
195 $sql .=
" FROM ".$this->db->prefix().
"workstation_workstation as w";
196 $sql .=
" WHERE 1 = 1";
197 if (!empty($fk_product) && $fk_product > 0) {
198 $sql .=
" AND w.fk_product = ".((int) $fk_product);
200 $sql .=
" AND w.entity IN (".getEntity(
'workstation').
")";
202 if (is_array($exclude) && !empty($exclude)) {
203 $sql .=
' AND w.rowid NOT IN('.$this->db->sanitize(implode(
',', $exclude)).
')';
206 $sql .=
" ORDER BY ".$orderBy;
208 dol_syslog(get_class($this).
'::loadWorkstations', LOG_DEBUG);
209 $resql = $this->db->query($sql);
211 $num = $this->db->num_rows($resql);
214 $obj = $this->db->fetch_object($resql);
216 $this->cache_workstations[$obj->rowid][
'id'] = $obj->rowid;
217 $this->cache_workstations[$obj->rowid][
'ref'] = $obj->ref;
218 $this->cache_workstations[$obj->rowid][
'label'] = $obj->label;
219 $this->cache_workstations[$obj->rowid][
'type'] = $obj->type;
220 $this->cache_workstations[$obj->rowid][
'nb_operators_required'] = $obj->nb_operators_required;
221 $this->cache_workstations[$obj->rowid][
'thm_operator_estimated'] = $obj->thm_operator_estimated;
222 $this->cache_workstations[$obj->rowid][
'thm_machine_estimated'] = $obj->thm_machine_estimated;
244 if (empty($final_label)) {
245 $final_label = $tab[
'label'];
248 if (empty($tab[
'parent_id'])) {
251 if (!empty($this->cache_warehouses[$tab[
'parent_id']])) {
252 $final_label = $this->cache_warehouses[$tab[
'parent_id']][
'label'].
' >> '.$final_label;
253 return $this->
get_parent_path($this->cache_warehouses[$tab[
'parent_id']], $final_label);
286 public function selectWarehouses($selected =
'', $htmlname =
'idwarehouse', $filterstatus =
'', $empty = 0, $disabled = 0, $fk_product = 0, $empty_label =
'', $showstock = 0, $forcecombo = 0, $events = array(), $morecss =
'minwidth200', $exclude = array(), $showfullpath = 1, $stockMin =
false, $orderBy =
'e.ref', $multiselect = 0)
288 global $conf, $langs, $user, $hookmanager;
290 dol_syslog(get_class($this).
"::selectWarehouses $selected, $htmlname, $filterstatus, $empty, $disabled, $fk_product, $empty_label, $showstock, $forcecombo, $morecss", LOG_DEBUG);
293 if (empty($conf->global->ENTREPOT_EXTRA_STATUS)) {
296 if (!empty($fk_product) && $fk_product > 0) {
297 $this->cache_warehouses = array();
300 $this->
loadWarehouses($fk_product,
'', $filterstatus,
true, $exclude, $stockMin, $orderBy);
301 $nbofwarehouses = count($this->cache_warehouses);
303 if ($conf->use_javascript_ajax && !$forcecombo) {
304 include_once DOL_DOCUMENT_ROOT.
'/core/lib/ajax.lib.php';
306 $out .= $comboenhancement;
309 if (strpos($htmlname,
'search_') !== 0) {
310 if (empty($user->fk_warehouse) || $user->fk_warehouse == -1) {
311 if (is_scalar($selected) && ($selected ==
'-2' || $selected ==
'ifone') && !empty($conf->global->MAIN_DEFAULT_WAREHOUSE)) {
312 $selected = $conf->global->MAIN_DEFAULT_WAREHOUSE;
315 if (is_scalar($selected) && ($selected ==
'-2' || $selected ==
'ifone') && !empty($conf->global->MAIN_DEFAULT_WAREHOUSE_USER)) {
316 $selected = $user->fk_warehouse;
321 $out .=
'<select '.($multiselect ?
'multiple ' :
'').
'class="flat'.($morecss ?
' '.$morecss :
'').
'"'.($disabled ?
' disabled' :
'');
322 $out .=
' id="'.$htmlname.
'" name="'.($htmlname.($multiselect?
'[]':
'').($disabled ?
'_disabled' :
'')).
'"';
326 $out .=
'<option value="-1">'.($empty_label ? $empty_label :
' ').
'</option>';
328 foreach ($this->cache_warehouses as $id => $arraytypes) {
331 $label .= $arraytypes[
'full_label'];
333 $label .= $arraytypes[
'label'];
335 if (($fk_product || ($showstock > 0)) && ($arraytypes[
'stock'] != 0 || ($showstock > 0))) {
336 if ($arraytypes[
'stock'] <= 0) {
337 $label .=
' <span class="text-warning">('.$langs->trans(
"Stock").
':'.$arraytypes[
'stock'].
')</span>';
339 $label .=
' <span class="opacitymedium">('.$langs->trans(
"Stock").
':'.$arraytypes[
'stock'].
')</span>';
343 $out .=
'<option value="'.$id.
'"';
344 if (is_array($selected)) {
345 if (in_array($id, $selected)) {
349 if ($selected == $id || (preg_match(
'/^ifone/', $selected) && $nbofwarehouses == 1)) {
353 $out .=
' data-html="'.dol_escape_htmltag($label).
'"';
360 $out .=
'<input type="hidden" name="'.$htmlname.
'" value="'.(($selected > 0) ? $selected :
'').
'">';
364 'selected' => $selected,
365 'htmlname' => $htmlname,
366 'filterstatus' => $filterstatus,
368 'disabled ' => $disabled,
369 'fk_product' => $fk_product,
370 'empty_label' => $empty_label,
371 'showstock' => $showstock,
372 'forcecombo' => $forcecombo,
374 'morecss' => $morecss,
375 'exclude' => $exclude,
376 'showfullpath' => $showfullpath,
377 'stockMin' => $stockMin,
378 'orderBy' => $orderBy
381 $reshook = $hookmanager->executeHooks(
'selectWarehouses', $parameters, $this);
383 $out = $hookmanager->resPrint;
384 } elseif ($reshook == 0) {
385 $out .= $hookmanager->resPrint;
410 public function selectWorkstations($selected =
'', $htmlname =
'idworkstations', $empty = 0, $disabled = 0, $fk_product = 0, $empty_label =
'', $forcecombo = 0, $events = array(), $morecss =
'minwidth200', $exclude = array(), $showfullpath = 1, $orderBy =
'e.ref')
412 global $conf, $langs, $user, $hookmanager;
414 dol_syslog(get_class($this).
"::selectWorkstations $selected, $htmlname, $empty, $disabled, $fk_product, $empty_label, $forcecombo, $morecss", LOG_DEBUG);
418 if (!empty($fk_product) && $fk_product > 0) {
419 $this->cache_workstations = array();
423 $nbofworkstations = count($this->cache_workstations);
425 if ($conf->use_javascript_ajax && !$forcecombo) {
426 include_once DOL_DOCUMENT_ROOT.
'/core/lib/ajax.lib.php';
428 $out .= $comboenhancement;
431 if (strpos($htmlname,
'search_') !== 0) {
432 if (empty($user->fk_workstation) || $user->fk_workstation == -1) {
433 if (($selected ==
'-2' || $selected ==
'ifone') && !empty($conf->global->MAIN_DEFAULT_WORKSTATION)) {
434 $selected = $conf->global->MAIN_DEFAULT_WORKSTATION;
437 if (($selected ==
'-2' || $selected ==
'ifone') && !empty($conf->global->MAIN_DEFAULT_WORKSTATION)) {
438 $selected = $user->fk_workstation;
443 $out .=
'<select class="flat'.($morecss ?
' '.$morecss :
'').
'"'.($disabled ?
' disabled' :
'').
' id="'.$htmlname.
'" name="'.($htmlname.($disabled ?
'_disabled' :
'')).
'">';
445 $out .=
'<option value="-1">'.($empty_label ? $empty_label :
' ').
'</option>';
447 foreach ($this->cache_workstations as $id => $arraytypes) {
448 $label = $arraytypes[
'label'];
450 $out .=
'<option value="'.$id.
'"';
451 if ($selected == $id || (preg_match(
'/^ifone/', $selected) && $nbofworkstations == 1)) {
454 $out .=
' data-html="'.dol_escape_htmltag($label).
'"';
461 $out .=
'<input type="hidden" name="'.$htmlname.
'" value="'.(($selected > 0) ? $selected :
'').
'">';
465 'selected' => $selected,
466 'htmlname' => $htmlname,
467 'filterstatus' => $filterstatus,
469 'disabled ' => $disabled,
470 'fk_product' => $fk_product,
471 'empty_label' => $empty_label,
472 'forcecombo' => $forcecombo,
474 'morecss' => $morecss,
475 'exclude' => $exclude,
476 'showfullpath' => $showfullpath,
477 'orderBy' => $orderBy
480 $reshook = $hookmanager->executeHooks(
'selectWorkstations', $parameters, $this);
482 $out = $hookmanager->resPrint;
483 } elseif ($reshook == 0) {
484 $out .= $hookmanager->resPrint;
502 if ($htmlname !=
"none") {
503 print
'<form method="POST" action="'.$page.
'">';
504 print
'<input type="hidden" name="action" value="setwarehouse">';
505 print
'<input type="hidden" name="token" value="'.newToken().
'">';
506 print
'<table class="nobordernopadding">';
510 print
'<td class="left"><input type="submit" class="button smallpaddingimp" value="'.$langs->trans(
"Modify").
'"></td>';
511 print
'</tr></table></form>';
514 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/entrepot.class.php';
515 $warehousestatic =
new Entrepot($this->db);
516 $warehousestatic->fetch($selected);
517 print $warehousestatic->getNomUrl();
537 public function select_measuring_units($name =
'measuring_units', $measuring_style =
'', $default =
'0', $adddefault = 0, $mode = 0)
555 public function selectMeasuringUnits($name =
'measuring_units', $measuring_style =
'', $default =
'0', $adddefault = 0, $mode = 0, $morecss =
'maxwidth125')
557 global $langs, $conf, $mysoc, $db;
559 $langs->load(
"other");
564 require_once DOL_DOCUMENT_ROOT.
'/core/class/cunits.class.php';
565 $measuringUnits =
new CUnits($db);
568 $filter[
't.active'] = 1;
569 if ($measuring_style) {
570 $filter[
't.unit_type'] = $measuring_style;
573 $result = $measuringUnits->fetchAll(
584 $return .=
'<select class="flat'.($morecss ?
' '.$morecss :
'').
'" name="'.$name.
'" id="'.$name.
'">';
585 if ($adddefault || $adddefault ===
'') {
586 $return .=
'<option value="0">'.($adddefault ? $langs->trans(
"Default") :
'').
'</option>';
589 foreach ($measuringUnits->records as $lines) {
590 $return .=
'<option value="';
592 $return .= $lines->short_label;
593 } elseif ($mode == 2) {
594 $return .= $lines->scale;
596 $return .= $lines->id;
599 if ($mode == 1 && $lines->short_label == $default) {
600 $return .=
' selected';
601 } elseif ($mode == 2 && $lines->scale == $default) {
602 $return .=
' selected';
603 } elseif ($mode == 0 && $lines->id == $default) {
604 $return .=
' selected';
607 if ($measuring_style ==
'time') {
608 $return .= $langs->trans(ucfirst($lines->label));
610 $return .= $langs->trans($lines->label);
612 $return .=
'</option>';
614 $return .=
'</select>';
636 $langs->load(
'products');
641 require_once DOL_DOCUMENT_ROOT.
'/core/class/cproductnature.class.php';
645 $filter[
't.active'] = 1;
647 $result = $productNature->fetchAll(
'',
'', 0, 0, $filter);
653 $return .=
'<select class="flat" name="'.$name.
'" id="'.$name.
'">';
654 if ($showempty || ($selected ==
'' || $selected ==
'-1')) {
655 $return .=
'<option value="-1"';
656 if ($selected ==
'' || $selected ==
'-1') {
657 $return .=
' selected';
659 $return .=
'></option>';
661 if (!empty($productNature->records) && is_array($productNature->records)) {
662 foreach ($productNature->records as $lines) {
663 $return .=
'<option value="';
665 $return .= $lines->label;
667 $return .= $lines->code;
672 if ($mode == 1 && $lines->label == $selected) {
673 $return .=
' selected';
674 } elseif ($lines->code == $selected) {
675 $return .=
' selected';
679 $return .= $langs->trans($lines->label);
680 $return .=
'</option>';
683 $return .=
'</select>';
709 public function selectLotStock($selected =
'', $htmlname =
'batch_id', $filterstatus =
'', $empty = 0, $disabled = 0, $fk_product = 0, $fk_entrepot = 0, $objectLines = array(), $empty_label =
'', $forcecombo = 0, $events = array(), $morecss =
'minwidth200')
711 global $conf, $langs;
713 dol_syslog(get_class($this).
"::selectLotStock $selected, $htmlname, $filterstatus, $empty, $disabled, $fk_product, $fk_entrepot, $empty_label, $forcecombo, $morecss", LOG_DEBUG);
716 $productIdArray = array();
717 if (!is_array($objectLines) || !count($objectLines)) {
718 if (!empty($fk_product) && $fk_product > 0) {
719 $productIdArray[] = (int) $fk_product;
722 foreach ($objectLines as $line) {
723 if ($line->fk_product) {
724 $productIdArray[] = $line->fk_product;
731 if ($conf->use_javascript_ajax && !$forcecombo) {
732 include_once DOL_DOCUMENT_ROOT.
'/core/lib/ajax.lib.php';
734 $out .= $comboenhancement;
737 $out .=
'<select class="flat'.($morecss ?
' '.$morecss :
'').
'"'.($disabled ?
' disabled' :
'').
' id="'.$htmlname.
'" name="'.($htmlname.($disabled ?
'_disabled' :
'')).
'">';
739 $out .=
'<option value="-1">'.($empty_label ? $empty_label :
' ').
'</option>';
741 if (!empty($fk_product) && $fk_product > 0) {
742 $productIdArray = array((
int) $fk_product);
744 foreach ($this->cache_lot as $key => $value) {
745 $productIdArray[] = $key;
749 foreach ($productIdArray as $productId) {
750 foreach ($this->cache_lot[$productId] as $id => $arraytypes) {
751 if (empty($fk_entrepot) || $fk_entrepot == $arraytypes[
'entrepot_id']) {
752 $label = $arraytypes[
'entrepot_label'].
' - ';
753 $label .= $arraytypes[
'batch'];
754 if ($arraytypes[
'qty'] <= 0) {
755 $label .=
' <span class=\'text-warning\'>('.$langs->trans(
"Stock").
' '.$arraytypes[
'qty'].
')</span>';
757 $label .=
' <span class=\'opacitymedium\'>('.$langs->trans(
"Stock").
' '.$arraytypes[
'qty'].
')</span>';
760 $out .=
'<option value="'.$id.
'"';
762 if ($selected == $id || ($selected ==
'ifone' && $nboflot == 1)) {
765 $out .=
' data-html="'.dol_escape_htmltag($label).
'"';
774 $out .=
'<input type="hidden" name="'.$htmlname.
'" value="'.(($selected > 0) ? $selected :
'').
'">';
792 public function selectLotDataList($htmlname =
'batch_id', $empty = 0, $fk_product = 0, $fk_entrepot = 0, $objectLines = array())
796 dol_syslog(get_class($this).
"::selectLotDataList $htmlname, $empty, $fk_product, $fk_entrepot", LOG_DEBUG);
799 $productIdArray = array();
800 if (!is_array($objectLines) || !count($objectLines)) {
801 if (!empty($fk_product) && $fk_product > 0) {
802 $productIdArray[] = (int) $fk_product;
805 foreach ($objectLines as $line) {
806 if ($line->fk_product) {
807 $productIdArray[] = $line->fk_product;
814 $out .=
'<datalist id="'.$htmlname.
'" >';
816 if (!empty($fk_product) && $fk_product > 0) {
817 $productIdArray = array((
int) $fk_product);
819 foreach ($this->cache_lot as $key => $value) {
820 $productIdArray[] = $key;
824 foreach ($productIdArray as $productId) {
825 if (array_key_exists($productId, $this->cache_lot)) {
826 foreach ($this->cache_lot[$productId] as $id => $arraytypes) {
827 if (empty($fk_entrepot) || $fk_entrepot == $arraytypes[
'entrepot_id']) {
828 $label = $arraytypes[
'entrepot_label'] .
' - ';
829 $label .= $arraytypes[
'batch'];
830 $out .=
'<option data-warehouse="'.dol_escape_htmltag($label).
'" value="' . $arraytypes[
'batch'] .
'">(' . $langs->trans(
'Stock Total') .
': ' . $arraytypes[
'qty'] .
')</option>';
835 $out .=
'</datalist>';
850 global $conf, $langs;
852 $cacheLoaded =
false;
853 if (empty($productIdArray)) {
855 $this->cache_lot = array();
858 if (count($productIdArray) && count($this->cache_lot)) {
860 foreach ($productIdArray as $productId) {
861 $cacheLoaded = !empty($this->cache_lot[$productId]) ? true :
false;
865 return count($this->cache_lot);
868 $this->cache_lot = array();
869 $productIdList = implode(
',', $productIdArray);
873 if (empty($hookmanager)) {
874 include_once DOL_DOCUMENT_ROOT .
'/core/class/hookmanager.class.php';
877 $hookmanager->initHooks(array(
'productdao'));
878 $parameters = array(
'productIdList' => $productIdList);
879 $reshook = $hookmanager->executeHooks(
'loadLotStock', $parameters, $this);
881 $this->error = $hookmanager->error;
884 if (!empty($hookmanager->resArray[
'batch_list']) && is_array($hookmanager->resArray[
'batch_list'])) {
885 $this->cache_lot = $hookmanager->resArray[
'batch_list'];
886 $batch_count = (int) $hookmanager->resArray[
'batch_count'];
892 $sql =
"SELECT pb.batch, pb.rowid, ps.fk_entrepot, pb.qty, e.ref as label, ps.fk_product";
893 $sql .=
" FROM ".$this->db->prefix().
"product_batch as pb";
894 $sql .=
" LEFT JOIN ".$this->db->prefix().
"product_stock as ps on ps.rowid = pb.fk_product_stock";
895 $sql .=
" LEFT JOIN ".$this->db->prefix().
"entrepot as e on e.rowid = ps.fk_entrepot AND e.entity IN (".
getEntity(
'stock').
")";
896 if (!empty($productIdList)) {
897 $sql .=
" WHERE ps.fk_product IN (".$this->db->sanitize($productIdList).
")";
899 $sql .=
" ORDER BY e.ref, pb.batch";
901 dol_syslog(get_class($this).
'::loadLotStock', LOG_DEBUG);
902 $resql = $this->db->query($sql);
904 $num = $this->db->num_rows($resql);
907 $obj = $this->db->fetch_object($resql);
908 $this->cache_lot[$obj->fk_product][$obj->rowid][
'id'] = $obj->rowid;
909 $this->cache_lot[$obj->fk_product][$obj->rowid][
'batch'] = $obj->batch;
910 $this->cache_lot[$obj->fk_product][$obj->rowid][
'entrepot_id'] = $obj->fk_entrepot;
911 $this->cache_lot[$obj->fk_product][$obj->rowid][
'entrepot_label'] = $obj->label;
912 $this->cache_lot[$obj->fk_product][$obj->rowid][
'qty'] = $obj->qty;
916 return $batch_count + $num;
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='')
Convert a html select field into an ajax combobox.
Class of dictionary of nature of product (used by imports)
Class of dictionary type of thirdparty (used by imports)
Class to manage warehouses.
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.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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.