';
+ if (!empty($object->lines) || ($object->status == $object::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines' && $action != 'editline')) {
+ print '
';
+ }
+
+ if (!empty($object->lines)) {
+ $object->printObjectLines($action, $mysoc, null, GETPOST('lineid', 'int'), 1, '/bom/tpl');
+ }
+
+ // Form to add new line
+ if ($object->status == 0 && $permissiontoadd && $action != 'selectlines') {
+ if ($action != 'editline') {
+ // Add services form
+ $parameters = array();
+ $reshook = $hookmanager->executeHooks('formAddObjectServiceLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
+ if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
+ if (empty($reshook))
+ $object->formAddObjectLine(1, $mysoc, null, '/bom/tpl');
+ }
}
}
@@ -578,6 +643,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
mrpCollapseBomManagement();
}
+ $res = $object->fetchLines();
// Buttons for actions
diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php
index 7ff9627f25b..ddb589a567d 100644
--- a/htdocs/bom/class/bom.class.php
+++ b/htdocs/bom/class/bom.class.php
@@ -23,6 +23,8 @@
// Put here all includes required by your class file
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
+require_once DOL_DOCUMENT_ROOT.'/workstation/class/workstation.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
@@ -399,6 +401,58 @@ class BOM extends CommonObject
return $result;
}
+ /**
+ * Load object lines in memory from the database by type of product
+ *
+ * @param int $typeproduct 0 type product, 1 type service
+
+ * @return int <0 if KO, 0 if not found, >0 if OK
+ */
+ public function fetchLinesbytypeproduct($typeproduct = 0)
+ {
+ $this->lines = array();
+
+ $objectlineclassname = get_class($this).'Line';
+ if (!class_exists($objectlineclassname)) {
+ $this->error = 'Error, class '.$objectlineclassname.' not found during call of fetchLinesCommon';
+ return -1;
+ }
+
+ $objectline = new $objectlineclassname($this->db);
+
+ $sql = "SELECT ".$objectline->getFieldList('l');
+ $sql .= " FROM ".$this->db->prefix().$objectline->table_element." as l";
+ $sql .= " LEFT JOIN ".$this->db->prefix()."product as p ON p.rowid = l.fk_product";
+ $sql .= " WHERE l.fk_".$this->db->escape($this->element)." = ".((int) $this->id);
+ $sql .= " AND p.fk_product_type = ". ((int) $typeproduct);
+ if (isset($objectline->fields['position'])) {
+ $sql .= $this->db->order('position', 'ASC');
+ }
+
+ $resql = $this->db->query($sql);
+ if ($resql) {
+ $num_rows = $this->db->num_rows($resql);
+ $i = 0;
+ while ($i < $num_rows) {
+ $obj = $this->db->fetch_object($resql);
+ if ($obj) {
+ $newline = new $objectlineclassname($this->db);
+ $newline->setVarsFromFetchObj($obj);
+
+ $this->lines[] = $newline;
+ }
+ $i++;
+ }
+
+ return $num_rows;
+ } else {
+ $this->error = $this->db->lasterror();
+ $this->errors[] = $this->error;
+ return -1;
+ }
+ }
+
+
/**
* Load list of objects in memory from the database.
*
@@ -515,7 +569,7 @@ class BOM extends CommonObject
* @param string $import_key Import Key
* @return int <0 if KO, Id of created object if OK
*/
- public function addLine($fk_product, $qty, $qty_frozen = 0, $disable_stock_change = 0, $efficiency = 1.0, $position = -1, $fk_bom_child = null, $import_key = null)
+ public function addLine($fk_product, $qty, $qty_frozen = 0, $disable_stock_change = 0, $efficiency = 1.0, $position = -1, $fk_bom_child = null, $import_key = null, $fk_unit = '')
{
global $mysoc, $conf, $langs, $user;
@@ -583,6 +637,7 @@ class BOM extends CommonObject
$this->line->fk_bom_child = $fk_bom_child;
$this->line->import_key = $import_key;
$this->line->position = $rankToUse;
+ $this->line->fk_unit = $fk_unit;
$result = $this->line->create($user);
@@ -612,9 +667,10 @@ class BOM extends CommonObject
* @param float $efficiency Efficiency in MO
* @param int $position Position of BOM-Line in BOM-Lines
* @param string $import_key Import Key
+ * @param int $fk_unit Unit of line
* @return int <0 if KO, Id of updated BOM-Line if OK
*/
- public function updateLine($rowid, $qty, $qty_frozen = 0, $disable_stock_change = 0, $efficiency = 1.0, $position = -1, $import_key = null)
+ public function updateLine($rowid, $qty, $qty_frozen = 0, $disable_stock_change = 0, $efficiency = 1.0, $position = -1, $import_key = null, $fk_unit = 0)
{
global $mysoc, $conf, $langs, $user;
@@ -684,6 +740,7 @@ class BOM extends CommonObject
$this->line->efficiency = $efficiency;
$this->line->import_key = $import_key;
$this->line->position = $rankToUse;
+ if(!empty($fk_unit)) $this->line->fk_unit = $fk_unit;
$result = $this->line->update($user);
@@ -1260,6 +1317,8 @@ class BOM extends CommonObject
*/
public function calculateCosts()
{
+ global $conf;
+
include_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
$this->unit_cost = 0;
$this->total_cost = 0;
@@ -1272,38 +1331,62 @@ class BOM extends CommonObject
foreach ($this->lines as &$line) {
$tmpproduct->cost_price = 0;
$tmpproduct->pmp = 0;
+ $result = $tmpproduct->fetch($line->fk_product, '', '', '', 0, 1, 1); // We discard selling price and language loading
- if (empty($line->fk_bom_child)) {
- $result = $tmpproduct->fetch($line->fk_product, '', '', '', 0, 1, 1); // We discard selling price and language loading
- if ($result < 0) {
- $this->error = $tmpproduct->error;
- return -1;
- }
- $line->unit_cost = price2num((!empty($tmpproduct->cost_price)) ? $tmpproduct->cost_price : $tmpproduct->pmp);
- if (empty($line->unit_cost)) {
- if ($productFournisseur->find_min_price_product_fournisseur($line->fk_product) > 0) {
- $line->unit_cost = $productFournisseur->fourn_unitprice;
+ if ($tmpproduct->type == $tmpproduct::TYPE_PRODUCT) {
+ if (empty($line->fk_bom_child)) {
+ if ($result < 0) {
+ $this->error = $tmpproduct->error;
+ return -1;
+ }
+ $line->unit_cost = price2num((!empty($tmpproduct->cost_price)) ? $tmpproduct->cost_price : $tmpproduct->pmp);
+ if (empty($line->unit_cost)) {
+ if ($productFournisseur->find_min_price_product_fournisseur($line->fk_product) > 0) {
+ $line->unit_cost = $productFournisseur->fourn_unitprice;
+ }
+ }
+
+ $line->total_cost = price2num($line->qty * $line->unit_cost, 'MT');
+
+ $this->total_cost += $line->total_cost;
+ } else {
+ $bom_child = new BOM($this->db);
+ $res = $bom_child->fetch($line->fk_bom_child);
+ if ($res > 0) {
+ $bom_child->calculateCosts();
+ $line->childBom[] = $bom_child;
+ $this->total_cost += $bom_child->total_cost * $line->qty;
+ } else {
+ $this->error = $bom_child->error;
+ return -2;
}
}
+ } else {
+ //Convert qty to hour
+ $unit = measuringUnitString($line->fk_unit, '', '', 1);
+ $qty = convertDurationtoHour($line->qty, $unit);
- $line->total_cost = price2num($line->qty * $line->unit_cost, 'MT');
+ if ($conf->workstation->enabled) {
+ if ($tmpproduct->fk_default_workstation) {
+ $workstation = new Workstation($this->db);
+ $res = $workstation->fetch($tmpproduct->fk_default_workstation);
+
+ if ($res > 0) $line->total_cost = price2num($qty * ($workstation->thm_operator_estimated + $workstation->thm_machine_estimated), 'MT');
+ else {
+ $this->error = $workstation->error;
+ return -3;
+ }
+ }
+ } else {
+ $line->total_cost = price2num($qty * $tmpproduct->cost_price, 'MT');
+ }
$this->total_cost += $line->total_cost;
- } else {
- $bom_child= new BOM($this->db);
- $res = $bom_child->fetch($line->fk_bom_child);
- if ($res>0) {
- $bom_child->calculateCosts();
- $line->childBom[] = $bom_child;
- $this->total_cost += $bom_child->total_cost * $line->qty;
- } else {
- $this->error = $bom_child->error;
- return -2;
- }
}
}
$this->total_cost = price2num($this->total_cost, 'MT');
+
if ($this->qty > 0) {
$this->unit_cost = price2num($this->total_cost / $this->qty, 'MU');
} elseif ($this->qty < 0) {
@@ -1478,6 +1561,7 @@ class BOMLine extends CommonObjectLine
'qty_frozen' => array('type'=>'smallint', 'label'=>'QuantityFrozen', 'enabled'=>1, 'visible'=>1, 'default'=>0, 'position'=>105, 'css'=>'maxwidth50imp', 'help'=>'QuantityConsumedInvariable'),
'disable_stock_change' => array('type'=>'smallint', 'label'=>'DisableStockChange', 'enabled'=>1, 'visible'=>1, 'default'=>0, 'position'=>108, 'css'=>'maxwidth50imp', 'help'=>'DisableStockChangeHelp'),
'efficiency' => array('type'=>'double(24,8)', 'label'=>'ManufacturingEfficiency', 'enabled'=>1, 'visible'=>0, 'default'=>1, 'position'=>110, 'notnull'=>1, 'css'=>'maxwidth50imp', 'help'=>'ValueOfEfficiencyConsumedMeans'),
+ 'fk_unit' => array('type'=>'integer', 'label'=>'Unit', 'enabled'=>1, 'visible'=>1, 'position'=>120, 'notnull'=>-1,),
'position' => array('type'=>'integer', 'label'=>'Rank', 'enabled'=>1, 'visible'=>0, 'default'=>0, 'position'=>200, 'notnull'=>1,),
'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>1000, 'notnull'=>-1,),
);
diff --git a/htdocs/bom/tpl/objectline_create.tpl.php b/htdocs/bom/tpl/objectline_create.tpl.php
index e895d534fac..41aeec4b96f 100644
--- a/htdocs/bom/tpl/objectline_create.tpl.php
+++ b/htdocs/bom/tpl/objectline_create.tpl.php
@@ -29,6 +29,8 @@
* $forceall (0 by default, 1 for supplier invoices/orders)
*/
+require_once DOL_DOCUMENT_ROOT."/product/class/html.formproduct.class.php";
+
// Protection to avoid direct call of template
if (empty($object) || !is_object($object)) {
print "Error: this template page cannot be called directly as an URL";
@@ -36,12 +38,18 @@ if (empty($object) || !is_object($object)) {
}
-global $forceall, $forcetoshowtitlelines;
+global $forceall, $forcetoshowtitlelines, $filtertype;
if (empty($forceall)) {
$forceall = 0;
}
+if (empty($filtertype)) $filtertype = 0;
+if (!empty($object->element) && $object->element == 'contrat' && empty($conf->global->STOCK_SUPPORT_SERVICES)) {
+ $filtertype = -1;
+}
+
+$formproduct = new FormProduct($object->db);
// Define colspan for the button 'Add'
$colspan = 3; // Columns: total ht + col edit + col delete
@@ -53,6 +61,7 @@ $objectline = new BOMLine($this->db);
print "\n";
$nolinesbefore = (count($this->lines) == 0 || $forcetoshowtitlelines);
+
if ($nolinesbefore) {
print '';
if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) {
@@ -62,16 +71,24 @@ if ($nolinesbefore) {
print '
'.$langs->trans('AddNewLine').' ';
print '';
print ''.$langs->trans('Qty').' ';
- if (!empty($conf->global->PRODUCT_USE_UNITS)) {
- print '';
- print '';
- print $langs->trans('Unit');
- print ' ';
+
+ if ($filtertype != 1) {
+ if (!empty($conf->global->PRODUCT_USE_UNITS)) {
+ print '';
+ print '';
+ print $langs->trans('Unit');
+ print ' ';
+ }
+ print '' . $form->textwithpicto($langs->trans('QtyFrozen'), $langs->trans("QuantityConsumedInvariable")) . ' ';
+ print '' . $form->textwithpicto($langs->trans('DisableStockChange'), $langs->trans('DisableStockChangeHelp')) . ' ';
+ print '' . $form->textwithpicto($langs->trans('ManufacturingEfficiency'), $langs->trans('ValueOfMeansLoss')) . ' ';
+ } else {
+ print '' . $form->textwithpicto($langs->trans('Unit'), '').' ';
+ if ($conf->workstation->enabled) print '' . $form->textwithpicto($langs->trans('Workstation'), '') . ' ';
+ print '' . $form->textwithpicto($langs->trans('TotalCost'), '') . ' ';
}
- print ''.$form->textwithpicto($langs->trans('QtyFrozen'), $langs->trans("QuantityConsumedInvariable")).' ';
- print ''.$form->textwithpicto($langs->trans('DisableStockChange'), $langs->trans('DisableStockChangeHelp')).' ';
- print ''.$form->textwithpicto($langs->trans('ManufacturingEfficiency'), $langs->trans('ValueOfMeansLoss')).' ';
- print ' ';
+
+ print ' ';
print ' ';
}
print '';
@@ -88,25 +105,23 @@ print '';
// Predefined product/service
if (isModEnabled("product") || isModEnabled("service")) {
- if (!empty($conf->global->BOM_SUB_BOM)) {
+ if ($filtertype == 1) {
+ print $langs->trans("Service");
+ } elseif (!empty($conf->global->BOM_SUB_BOM)) {
print $langs->trans("Product");
}
echo '';
- $filtertype = 0;
- if (!empty($object->element) && $object->element == 'contrat' && empty($conf->global->STOCK_SUPPORT_SERVICES)) {
- $filtertype = -1;
- }
$statustoshow = -1;
if (!empty($conf->global->ENTREPOT_EXTRA_STATUS)) {
// hide products in closed warehouse, but show products for internal transfer
- $form->select_produits(GETPOST('idprod', 'int'), 'idprod', $filtertype, $conf->product->limit_size, $buyer->price_level, $statustoshow, 2, '', 1, array(), $buyer->id, '1', 0, 'maxwidth500', 0, 'warehouseopen,warehouseinternal', GETPOST('combinations', 'array'));
+ $form->select_produits(GETPOST('idprod', 'int'), (($filtertype == 1) ? 'idprodservice' : 'idprod'), $filtertype, $conf->product->limit_size, $buyer->price_level, $statustoshow, 2, '', 1, array(), $buyer->id, '1', 0, 'maxwidth500', 0, 'warehouseopen,warehouseinternal', GETPOST('combinations', 'array'));
} else {
- $form->select_produits(GETPOST('idprod', 'int'), 'idprod', $filtertype, $conf->product->limit_size, $buyer->price_level, $statustoshow, 2, '', 1, array(), $buyer->id, '1', 0, 'maxwidth500', 0, '', GETPOST('combinations', 'array'));
+ $form->select_produits(GETPOST('idprod', 'int'), (($filtertype == 1) ? 'idprodservice' : 'idprod'), $filtertype, $conf->product->limit_size, $buyer->price_level, $statustoshow, 2, '', 1, array(), $buyer->id, '1', 0, 'maxwidth500', 0, '', GETPOST('combinations', 'array'));
}
echo ' ';
}
-if (!empty($conf->global->BOM_SUB_BOM)) {
+if (!empty($conf->global->BOM_SUB_BOM) && $filtertype!=1) {
print ''.$langs->trans("or").' '.$langs->trans("BOM");
// TODO Add component to select a BOM
$form->select_bom();
@@ -118,35 +133,57 @@ $coldisplay++;
print ' ';
print ' ';
-if (!empty($conf->global->PRODUCT_USE_UNITS)) {
+if ($filtertype != 1) {
+ if (!empty($conf->global->PRODUCT_USE_UNITS)) {
+ $coldisplay++;
+ print '';
+ print ' ';
+ }
+
$coldisplay++;
- print '';
+ print ' ';
+ print ' ';
+
+
+ $coldisplay++;
+ print ' ';
+ print ' ';
+
+ $coldisplay++;
+ print '';
+ print ' ';
+ print ' ';
+
+ $coldisplay++;
+ print '';
+ print ' ';
+ print ' ';
+} else {
+ $coldisplay++;
+ require_once DOL_DOCUMENT_ROOT.'/core/class/cunits.class.php';
+ $cUnit = new CUnits($this->db);
+ $fk_unit_default = $cUnit->getUnitFromCode('h', 'short_label', 'time');
+ print '';
+ print $formproduct->selectMeasuringUnits("fk_unit", "time", $fk_unit_default, 0, 0);
+ print ' ';
+
+ $coldisplay++;
+ print '';
+ print ' ';
+ print ' ';
+
+ $coldisplay++;
+ print '';
+ print ' ';
print ' ';
}
-$coldisplay++;
-print ' ';
-print ' ';
+ $coldisplay += $colspan;
+ print '';
+ print ' ';
+ print ' ';
+ print ' ';
-$coldisplay++;
-print ' ';
-print ' ';
-
-$coldisplay++;
-print '';
-print ' ';
-print ' ';
-
-$coldisplay++;
-print '';
-print ' ';
-print ' ';
-
-$coldisplay += $colspan;
-print '';
-print ' ';
-print ' ';
-print '';
if (is_object($objectline)) {
print $objectline->showOptionals($extrafields, 'edit', array('style'=>$bcnd[$var], 'colspan'=>$coldisplay), '', '', 1, 'line');
@@ -175,6 +212,27 @@ jQuery(document).ready(function() {
}
}
});
+
+ //change unit selected if we change service selected
+
+ $('#idprodservice').change(function(){
+ var idproduct = $(this).val();
+
+ $.ajax({
+ url : ""
+ ,type: 'POST'
+ ,data: {
+ 'action': 'getDurationUnitByProduct'
+ ,'idproduct' : idproduct
+ }
+ }).done(function(data) {
+
+ console.log(data);
+ var data = JSON.parse(data);
+ $("#fk_unit").val(data).change();
+ });
+ });
+
});
diff --git a/htdocs/bom/tpl/objectline_edit.tpl.php b/htdocs/bom/tpl/objectline_edit.tpl.php
index e5f24fa994f..0ce88fa359c 100644
--- a/htdocs/bom/tpl/objectline_edit.tpl.php
+++ b/htdocs/bom/tpl/objectline_edit.tpl.php
@@ -31,6 +31,9 @@
* $inputalsopricewithtax (0 by default, 1 to also show column with unit price including tax)
*/
+require_once DOL_DOCUMENT_ROOT."/product/class/html.formproduct.class.php";
+
+
// Protection to avoid direct call of template
if (empty($object) || !is_object($object)) {
print "Error, template page can't be called as URL";
@@ -38,12 +41,16 @@ if (empty($object) || !is_object($object)) {
}
-global $forceall;
+global $forceall, $filtertype;
if (empty($forceall)) {
$forceall = 0;
}
+if (empty($filtertype)) $filtertype = 0;
+
+$formproduct = new FormProduct($object->db);
+
// Define colspan for the button 'Add'
$colspan = 3; // Columns: total ht + col edit + col delete
@@ -108,28 +115,43 @@ if (($line->info_bits & 2) != 2) {
}
print '';
-if (!empty($conf->global->PRODUCT_USE_UNITS)) {
+if ($filtertype != 1) {
+ if (!empty($conf->global->PRODUCT_USE_UNITS)) {
+ $coldisplay++;
+ print '';
+ print ' ';
+ }
+
$coldisplay++;
- print '';
+ print ' qty_frozen ? ' checked="checked"' : '')) . '>';
+ print ' ';
+
+ $coldisplay++;
+ print ' disable_stock_change ? ' checked="checked"' : '')) . '">';
+ print ' ';
+
+ $coldisplay++;
+ print '';
+ print ' ';
+
+ $coldisplay++;
+ print '';
+ print ' ';
+} else {
+ $coldisplay++;
+ print '';
+ print $formproduct->selectMeasuringUnits("fk_unit", "time", ($line->fk_unit) ? $line->fk_unit : '', 0, 0);
+ print ' ';
+
+ $coldisplay++;
+ print '';
+ print ' ';
+
+ $coldisplay++;
+ print '';
print ' ';
}
-$coldisplay++;
-print ' qty_frozen ? ' checked="checked"' : '')).'>';
-print ' ';
-
-$coldisplay++;
-print ' disable_stock_change ? ' checked="checked"' : '')).'">';
-print ' ';
-
-$coldisplay++;
-print '';
-print ' ';
-
-$coldisplay++;
-print '';
-print ' ';
-
$coldisplay += $colspan;
print '';
$coldisplay += $colspan;
diff --git a/htdocs/bom/tpl/objectline_title.tpl.php b/htdocs/bom/tpl/objectline_title.tpl.php
index dff3a38ccd2..f93fb59fe0d 100644
--- a/htdocs/bom/tpl/objectline_title.tpl.php
+++ b/htdocs/bom/tpl/objectline_title.tpl.php
@@ -38,6 +38,10 @@ if (empty($object) || !is_object($object)) {
print "Error, template page can't be called as URL";
exit;
}
+
+global $filtertype;
+if (empty($filtertype)) $filtertype = 0;
+
print "\n";
@@ -53,30 +57,42 @@ if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) {
// Product or sub-bom
print ' '.$langs->trans('Description');
-if (!empty($conf->global->BOM_SUB_BOM)) {
+if (!empty($conf->global->BOM_SUB_BOM) && $filtertype != 1) {
print ' '.img_picto('', 'folder-open', 'class="paddingright"').$langs->trans("ExpandAll").' ';
print ''.img_picto('', 'folder', 'class="paddingright"').$langs->trans("UndoExpandAll").' ';
}
print ' ';
// Qty
-print ''.$form->textwithpicto($langs->trans('Qty'), $langs->trans("QtyRequiredIfNoLoss")).' ';
+print ''.$form->textwithpicto($langs->trans('Qty'), ($filtertype != 1) ? $langs->trans("QtyRequiredIfNoLoss") : '').' ';
-if (!empty($conf->global->PRODUCT_USE_UNITS)) {
- print ''.$langs->trans('Unit').' ';
+if ($filtertype != 1) {
+ if (!empty($conf->global->PRODUCT_USE_UNITS)) {
+ print '' . $langs->trans('Unit') . ' ';
+ }
+
+ // Qty frozen
+ print '' . $form->textwithpicto($langs->trans('QtyFrozen'), $langs->trans("QuantityConsumedInvariable")) . ' ';
+
+ // Disable stock change
+ print '' . $form->textwithpicto($langs->trans('DisableStockChange'), $langs->trans('DisableStockChangeHelp')) . ' ';
+
+ // Efficiency
+ print '' . $form->textwithpicto($langs->trans('ManufacturingEfficiency'), $langs->trans('ValueOfMeansLoss')) . ' ';
+
+ // Cost
+ print ''.$form->textwithpicto($langs->trans("TotalCost"), $langs->trans("BOMTotalCost")).' ';
+} else {
+ print '' . $form->textwithpicto($langs->trans('Unit'), '').' ';
+
+ if ($conf->workstation->enabled) print '' . $form->textwithpicto($langs->trans('DefaultWorkstation'), '') . ' ';
+
+ // Cost
+ print ''.$form->textwithpicto($langs->trans("TotalCost"), $langs->trans("BOMTotalCostService")).' ';
}
-// Qty frozen
-print ''.$form->textwithpicto($langs->trans('QtyFrozen'), $langs->trans("QuantityConsumedInvariable")).' ';
-// Disable stock change
-print ''.$form->textwithpicto($langs->trans('DisableStockChange'), $langs->trans('DisableStockChangeHelp')).' ';
-// Efficiency
-print ''.$form->textwithpicto($langs->trans('ManufacturingEfficiency'), $langs->trans('ValueOfMeansLoss')).' ';
-
-// Cost
-print ''.$form->textwithpicto($langs->trans("TotalCost"), $langs->trans("BOMTotalCost")).' ';
print ' '; // No width to allow autodim
diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php
index 61b394a3b0f..a3b9df0bdf0 100644
--- a/htdocs/bom/tpl/objectline_view.tpl.php
+++ b/htdocs/bom/tpl/objectline_view.tpl.php
@@ -34,12 +34,17 @@
* $type, $text, $description, $line
*/
+require_once DOL_DOCUMENT_ROOT.'/workstation/class/workstation.class.php';
+
// Protection to avoid direct call of template
if (empty($object) || !is_object($object)) {
print "Error, template page can't be called as URL";
exit;
}
+global $filtertype;
+if (empty($filtertype)) $filtertype = 0;
+
global $forceall, $senderissupplier, $inputalsopricewithtax, $outputalsopricetotalwithtax, $langs;
@@ -60,7 +65,9 @@ if (empty($outputalsopricetotalwithtax)) {
}
// add html5 elements
-$domData = ' data-element="'.$line->element.'"';
+if ($filtertype == 1) $domData = ' data-element="'.$line->element.'service"';
+else $domData = ' data-element="'.$line->element.'"';
+
$domData .= ' data-id="'.$line->id.'"';
$domData .= ' data-qty="'.$line->qty.'"';
$domData .= ' data-product_type="'.$line->product_type.'"';
@@ -100,29 +107,54 @@ $coldisplay++;
echo price($line->qty, 0, '', 0, 0); // Yes, it is a quantity, not a price, but we just want the formating role of function price
print '';
-if (!empty($conf->global->PRODUCT_USE_UNITS)) {
- print '';
- $label = $tmpproduct->getLabelOfUnit('long');
- if ($label !== '') {
- print $langs->trans($label);
+if ($filtertype != 1) {
+ if (!empty($conf->global->PRODUCT_USE_UNITS)) {
+ print ' ';
+ $label = $tmpproduct->getLabelOfUnit('long');
+ if ($label !== '') {
+ print $langs->trans($label);
+ }
+ print ' ';
}
+
+ print '';
+ $coldisplay++;
+ echo $line->qty_frozen ? yn($line->qty_frozen) : '';
print ' ';
+ print '';
+ $coldisplay++;
+ echo $line->disable_stock_change ? yn($line->disable_stock_change) : ''; // Yes, it is a quantity, not a price, but we just want the formating role of function price
+ print ' ';
+
+ print '';
+ $coldisplay++;
+ echo $line->efficiency;
+ print ' ';
+} else {
+ //Unité
+ print '';
+ $coldisplay++;
+
+ if (!empty($line->fk_unit)) {
+ require_once DOL_DOCUMENT_ROOT.'/core/class/cunits.class.php';
+ $unit = new CUnits($this->db);
+ $unit->fetch($line->fk_unit);
+ print (isset($unit->label) ? " ".$langs->trans(ucwords($unit->label))." " : '');
+ }
+
+ print ' ';
+
+ //Poste de travail
+ if ($conf->workstation->enabled) {
+ $workstation = new Workstation($object->db);
+ $res = $workstation->fetch($tmpproduct->fk_default_workstation);
+
+ print '';
+ $coldisplay++;
+ if ($res > 0) echo $workstation->getNomUrl();
+ print ' ';
+ }
}
-
-print '';
-$coldisplay++;
-echo $line->qty_frozen ? yn($line->qty_frozen) : '';
-print ' ';
-print '';
-$coldisplay++;
-echo $line->disable_stock_change ? yn($line->disable_stock_change) : ''; // Yes, it is a quantity, not a price, but we just want the formating role of function price
-print ' ';
-
-print '';
-$coldisplay++;
-echo $line->efficiency;
-print ' ';
-
$total_cost = 0;
print '';
$coldisplay++;
diff --git a/htdocs/core/class/cunits.class.php b/htdocs/core/class/cunits.class.php
index dfc22fd37ec..102bbbda652 100644
--- a/htdocs/core/class/cunits.class.php
+++ b/htdocs/core/class/cunits.class.php
@@ -420,15 +420,16 @@ class CUnits // extends CommonObject
* Get unit from code
* @param string $code code of unit
* @param string $mode 0= id , short_label=Use short label as value, code=use code
+ * @param string $unit_type weight,size,surface,volume,qty,time...
* @return int <0 if KO, Id of code if OK
*/
- public function getUnitFromCode($code, $mode = 'code')
+ public function getUnitFromCode($code, $mode = 'code', $unit_type = '')
{
if ($mode == 'short_label') {
- return dol_getIdFromCode($this->db, $code, 'c_units', 'short_label', 'rowid');
+ return dol_getIdFromCode($this->db, $code, 'c_units', 'short_label', 'rowid', 0, ' AND unit_type = "'.$this->db->escape($unit_type).'"');
} elseif ($mode == 'code') {
- return dol_getIdFromCode($this->db, $code, 'c_units', 'code', 'rowid');
+ return dol_getIdFromCode($this->db, $code, 'c_units', 'code', 'rowid', 0, ' AND unit_type = "'. $this->db->escape($unit_type) .'"');
}
return $code;
diff --git a/htdocs/core/lib/date.lib.php b/htdocs/core/lib/date.lib.php
index f8d11b4bc82..d2383a14dfc 100644
--- a/htdocs/core/lib/date.lib.php
+++ b/htdocs/core/lib/date.lib.php
@@ -319,6 +319,27 @@ function convertSecondToTime($iSecond, $format = 'all', $lengthOfDay = 86400, $l
}
+/** Convert duration to hour
+ *
+ * @param int $duration_value Duration value
+ * @param int $duration_unit Duration unit
+ * @return int $result
+ */
+function convertDurationtoHour($duration_value, $duration_unit)
+{
+ $result = 0;
+
+ if ($duration_unit == 's') $result = $duration_value / 3600;
+ if ($duration_unit == 'i') $result = $duration_value / 60;
+ if ($duration_unit == 'h') $result = $duration_value;
+ if ($duration_unit == 'd') $result = $duration_value * 24;
+ if ($duration_unit == 'w') $result = $duration_value * 24 * 7;
+ if ($duration_unit == 'm') $result = $duration_value * 730.484;
+ if ($duration_unit == 'y') $result = $duration_value * 365 * 24;
+
+ return $result;
+}
+
/**
* Generate a SQL string to make a filter into a range (for second of date until last second of date).
* This method allows to maje SQL request that will deal correctly the timezone of server.
diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php
index 7b3aa47af17..a3c538954dc 100644
--- a/htdocs/core/lib/functions.lib.php
+++ b/htdocs/core/lib/functions.lib.php
@@ -8543,10 +8543,11 @@ function dol_osencode($str)
* @param string $fieldkey Field to search the key into
* @param string $fieldid Field to get
* @param int $entityfilter Filter by entity
+ * @param string $filters Filter on other fields
* @return int <0 if KO, Id of code if OK
* @see $langs->getLabelFromKey
*/
-function dol_getIdFromCode($db, $key, $tablename, $fieldkey = 'code', $fieldid = 'id', $entityfilter = 0)
+function dol_getIdFromCode($db, $key, $tablename, $fieldkey = 'code', $fieldid = 'id', $entityfilter = 0, $filters = '')
{
global $cache_codes;
@@ -8568,6 +8569,9 @@ function dol_getIdFromCode($db, $key, $tablename, $fieldkey = 'code', $fieldid =
if (!empty($entityfilter)) {
$sql .= " AND entity IN (".getEntity($tablename).")";
}
+ if ($filters) {
+ $sql .= $filters;
+ }
$resql = $db->query($sql);
if ($resql) {
diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql
index 01cbb851d51..a10b4202079 100644
--- a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql
+++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql
@@ -147,6 +147,10 @@ ALTER TABLE llx_user CHANGE COLUMN note note_private text;
UPDATE llx_c_effectif SET code='EF101-500', libelle='101 - 500' WHERE code='EF100-500';
+
+ALTER TABLE llx_product ADD COLUMN fk_default_workstation integer DEFAULT NULL;
+ALTER TABLE llx_bom_bomline ADD COLUMN fk_unit integer DEFAULT NULL;
+
ALTER TABLE llx_rights_def ADD COLUMN tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
@@ -170,3 +174,4 @@ create table llx_element_categorie
ALTER TABLE llx_element_categorie ADD UNIQUE INDEX idx_element_categorie_idx (fk_element, fk_categorie);
ALTER TABLE llx_element_categorie ADD CONSTRAINT fk_element_categorie_fk_categorie FOREIGN KEY (fk_categorie) REFERENCES llx_fk_categorie(rowid);
+
diff --git a/htdocs/install/mysql/tables/llx_bom_bomline.sql b/htdocs/install/mysql/tables/llx_bom_bomline.sql
index e7eae15fc15..eae1f6c6662 100644
--- a/htdocs/install/mysql/tables/llx_bom_bomline.sql
+++ b/htdocs/install/mysql/tables/llx_bom_bomline.sql
@@ -25,6 +25,7 @@ CREATE TABLE llx_bom_bomline(
qty_frozen smallint DEFAULT 0,
disable_stock_change smallint DEFAULT 0,
efficiency double(24,8) NOT NULL DEFAULT 1,
+ fk_unit integer NULL,
position integer NOT NULL DEFAULT 0
-- END MODULEBUILDER FIELDS
) ENGINE=innodb;
diff --git a/htdocs/install/mysql/tables/llx_product.sql b/htdocs/install/mysql/tables/llx_product.sql
index a234ae8ddb1..266b561f466 100644
--- a/htdocs/install/mysql/tables/llx_product.sql
+++ b/htdocs/install/mysql/tables/llx_product.sql
@@ -108,4 +108,5 @@ create table llx_product
mandatory_period tinyint DEFAULT 0, -- is used to signal to the user that the start and end dates are mandatory for this type of product the fk_product_type == 1 (service) (non-blocking action)
fk_default_bom integer DEFAULT NULL
+ fk_default_workstation integer DEFAULT NULL
)ENGINE=innodb;
diff --git a/htdocs/langs/fr_FR/mrp.lang b/htdocs/langs/fr_FR/mrp.lang
index 709ff68b963..2a905a76530 100644
--- a/htdocs/langs/fr_FR/mrp.lang
+++ b/htdocs/langs/fr_FR/mrp.lang
@@ -82,6 +82,9 @@ ProductsToProduce=Produits à produire
UnitCost=Coût unitaire
TotalCost=Coût total
BOMTotalCost=Le coût de production de cette nomenclature basé sur chaque quantité et produit à consommer (utilise le prix de revient si défini, sinon le PMP si défini, sinon le meilleur prix d'achat)
+BOMTotalCostService=Si le module "Poste de travail" est activé, alors le calcul est "quantité (convertie en heures) x thm du poste de travail", sinon "quantité (convertie en heures) x prix de revient du service"
+BOMProductsList=Liste des composants
+BOMServicesList=Liste des services
GoOnTabProductionToProduceFirst=Vous devez avoir la production pour clôturer un Ordre de Fabrication (voir onglet '%s'). Mais vous pouvez l'annuler.
ErrorAVirtualProductCantBeUsedIntoABomOrMo=Un kit ne peut pas être utilisé dans une Nomenclature ou un Ordre de fabrication.
Workstation=Poste de travail
@@ -91,6 +94,7 @@ WorkstationSetup = Configuration du module Poste de travail
WorkstationSetupPage = Configuration du module Poste de travail
WorkstationList=Liste des postes de travail
WorkstationCreate=Ajouter un nouveau poste de travail
+DefaultWorkstation=Poste de travail par défaut
ConfirmEnableWorkstation=Voulez-vous vraiment activer le poste de travail %s ?
EnableAWorkstation=Activer le module Poste de travail
ConfirmDisableWorkstation=Voulez-vous vraiment désactiver la station de travail %s ?
diff --git a/htdocs/product/card.php b/htdocs/product/card.php
index 86a5635e9de..5d1613b05f2 100644
--- a/htdocs/product/card.php
+++ b/htdocs/product/card.php
@@ -55,6 +55,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/modules/product/modules_product.class.php'
require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
+require_once DOL_DOCUMENT_ROOT.'/workstation/class/workstation.class.php';
if (isModEnabled('propal')) {
require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
@@ -558,6 +559,7 @@ if (empty($reshook)) {
$object->duration_value = $duration_value;
$object->duration_unit = $duration_unit;
$object->fk_default_warehouse = GETPOST('fk_default_warehouse');
+ $object->fk_default_workstation = GETPOST('fk_default_workstation');
$object->seuil_stock_alerte = GETPOST('seuil_stock_alerte') ?GETPOST('seuil_stock_alerte') : 0;
$object->desiredstock = GETPOST('desiredstock') ?GETPOST('desiredstock') : 0;
$object->canvas = GETPOST('canvas');
@@ -723,6 +725,7 @@ if (empty($reshook)) {
$object->status_batch = GETPOST('status_batch', 'aZ09');
$object->batch_mask = GETPOST('batch_mask', 'alpha');
$object->fk_default_warehouse = GETPOST('fk_default_warehouse');
+ $object->fk_default_workstation = GETPOST('fk_default_workstation');
// removed from update view so GETPOST always empty
/*
$object->seuil_stock_alerte = GETPOST('seuil_stock_alerte');
@@ -1441,7 +1444,6 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
// Description (used in invoice, propal...)
print ' '.$langs->trans("Description").' ';
-
$doleditor = new DolEditor('desc', GETPOST('desc', 'restricthtml'), '', 160, 'dolibarr_details', '', false, true, getDolGlobalString('FCKEDITOR_ENABLE_PRODUCTDESC'), ROWS_4, '90%');
$doleditor->Create();
@@ -1485,6 +1487,14 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
}
}
+ if ($type == 1 && $conf->workstation->enabled) {
+ // Default workstation
+ print ' '.$langs->trans("DefaultWorkstation").' ';
+ print img_picto($langs->trans("DefaultWorkstation"), 'workstation', 'class="pictofixedwidth"');
+ print $formproduct->selectWorkstations($object->fk_default_workstation, 'fk_default_workstation', 1);
+ print ' ';
+ }
+
// Duration
if ($type == 1) {
print ''.$langs->trans("Duration").' ';
@@ -2024,6 +2034,15 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
print ' ';
*/
}
+
+ if ($object->isService() && $conf->workstation->enabled) {
+ // Default workstation
+ print ''.$langs->trans("DefaultWorkstation").' ';
+ print img_picto($langs->trans("DefaultWorkstation"), 'workstation', 'class="pictofixedwidth"');
+ print $formproduct->selectWorkstations($object->fk_default_workstation, 'fk_default_workstation', 1);
+ print ' ';
+ }
+
/*
else
{
@@ -2505,6 +2524,15 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
print '';
}
+ if ($object->isService() && $conf->workstation->enabled) {
+ $workstation = new Workstation($db);
+ $res = $workstation->fetch($object->fk_default_workstation);
+
+ print ''.$langs->trans("DefaultWorkstation").' ';
+ print (!empty($workstation->id) ? $workstation->getNomUrl(1) : '');
+ print ' ';
+ }
+
// Parent product.
if (!empty($conf->variants->enabled) && ($object->isProduct() || $object->isService())) {
$combination = new ProductCombination($db);
diff --git a/htdocs/product/class/html.formproduct.class.php b/htdocs/product/class/html.formproduct.class.php
index 4ede9e1e297..a21ff6348e6 100644
--- a/htdocs/product/class/html.formproduct.class.php
+++ b/htdocs/product/class/html.formproduct.class.php
@@ -42,6 +42,7 @@ class FormProduct
// Cache arrays
public $cache_warehouses = array();
public $cache_lot = array();
+ public $cache_workstations = array();
/**
@@ -172,6 +173,63 @@ class FormProduct
}
}
+ /**
+ * Load in cache array list of workstations
+ * If fk_product is not 0, we do not use cache
+ *
+ * @param int $fk_product Add quantity of stock in label for product with id fk_product. Nothing if 0.
+ * @param array $exclude warehouses ids to exclude
+ * @param string $orderBy [='e.ref'] Order by
+ * @return int Nb of loaded lines, 0 if already loaded, <0 if KO
+ * @throws Exception
+ */
+ public function loadWorkstations($fk_product = 0, $exclude = array(), $orderBy = 'w.ref')
+ {
+ global $conf, $langs;
+
+ if (empty($fk_product) && count($this->cache_workstations)) {
+ return 0; // Cache already loaded and we do not want a list with information specific to a product
+ }
+
+ $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";
+ $sql .= " FROM ".$this->db->prefix()."workstation_workstation as w";
+ $sql .= " WHERE 1 = 1";
+ if (!empty($fk_product) && $fk_product > 0) {
+ $sql .= " AND w.fk_product = ".((int) $fk_product);
+ }
+ $sql .= " AND w.entity IN (".getEntity('workstation').")";
+
+ if (is_array($exclude) && !empty($exclude)) {
+ $sql .= ' AND w.rowid NOT IN('.$this->db->sanitize(implode(',', $exclude)).')';
+ }
+
+ $sql .= " ORDER BY ".$orderBy;
+
+ dol_syslog(get_class($this).'::loadWorkstations', LOG_DEBUG);
+ $resql = $this->db->query($sql);
+ if ($resql) {
+ $num = $this->db->num_rows($resql);
+ $i = 0;
+ while ($i < $num) {
+ $obj = $this->db->fetch_object($resql);
+
+ $this->cache_workstations[$obj->rowid]['id'] = $obj->rowid;
+ $this->cache_workstations[$obj->rowid]['ref'] = $obj->ref;
+ $this->cache_workstations[$obj->rowid]['label'] = $obj->label;
+ $this->cache_workstations[$obj->rowid]['type'] = $obj->type;
+ $this->cache_workstations[$obj->rowid]['nb_operators_required'] = $obj->nb_operators_required;
+ $this->cache_workstations[$obj->rowid]['thm_operator_estimated'] = $obj->thm_operator_estimated;
+ $this->cache_workstations[$obj->rowid]['thm_machine_estimated'] = $obj->thm_machine_estimated;
+ $i++;
+ }
+
+ return $num;
+ } else {
+ dol_print_error($this->db);
+ return -1;
+ }
+ }
+
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Return full path to current warehouse in $tab (recursive function)
@@ -320,6 +378,104 @@ class FormProduct
return $out;
}
+ /**
+ * Return list of workstations
+ *
+ * @param string|int $selected Id of preselected warehouse ('' or '-1' for no value, 'ifone' and 'ifonenodefault' = select value if one value otherwise no value, '-2' to use the default value from setup)
+ * @param string $htmlname Name of html select html
+ * @param int $empty 1=Can be empty, 0 if not
+ * @param int $disabled 1=Select is disabled
+ * @param int $fk_product Add quantity of stock in label for product with id fk_product. Nothing if 0.
+ * @param string $empty_label Empty label if needed (only if $empty=1)
+ * @param int $forcecombo 1=Force combo iso ajax select2
+ * @param array $events Events to add to select2
+ * @param string $morecss Add more css classes to HTML select
+ * @param array $exclude Warehouses ids to exclude
+ * @param int $showfullpath 1=Show full path of name (parent ref into label), 0=Show only ref of current warehouse
+ * @param string $orderBy [='e.ref'] Order by
+ * @return string HTML select
+ *
+ * @throws Exception
+ */
+ 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')
+ {
+ global $conf, $langs, $user, $hookmanager;
+
+ dol_syslog(get_class($this)."::selectWorkstations $selected, $htmlname, $empty, $disabled, $fk_product, $empty_label, $forcecombo, $morecss", LOG_DEBUG);
+
+ $out = '';
+ if (!empty($fk_product) && $fk_product > 0) {
+ $this->cache_workstations = array();
+ }
+
+ $this->loadWorkstations($fk_product);
+ $nbofworkstations = count($this->cache_workstations);
+
+ if ($conf->use_javascript_ajax && !$forcecombo) {
+ include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
+ $comboenhancement = ajax_combobox($htmlname, $events);
+ $out .= $comboenhancement;
+ }
+
+ if (strpos($htmlname, 'search_') !== 0) {
+ if (empty($user->fk_workstation) || $user->fk_workstation == -1) {
+ if (($selected == '-2' || $selected == 'ifone') && !empty($conf->global->MAIN_DEFAULT_WORKSTATION)) {
+ $selected = $conf->global->MAIN_DEFAULT_WORKSTATION;
+ }
+ } else {
+ if (($selected == '-2' || $selected == 'ifone') && !empty($conf->global->MAIN_DEFAULT_WORKSTATION)) {
+ $selected = $user->fk_workstation;
+ }
+ }
+ }
+
+ $out .= '';
+ if ($empty) {
+ $out .= ''.($empty_label ? $empty_label : ' ').' ';
+ }
+ foreach ($this->cache_workstations as $id => $arraytypes) {
+ $label = $arraytypes['label'];
+
+ $out .= '';
+ }
+
+ $parameters = array(
+ 'selected' => $selected,
+ 'htmlname' => $htmlname,
+ 'filterstatus' => $filterstatus,
+ 'empty' => $empty,
+ 'disabled ' => $disabled,
+ 'fk_product' => $fk_product,
+ 'empty_label' => $empty_label,
+ 'forcecombo' => $forcecombo,
+ 'events' => $events,
+ 'morecss' => $morecss,
+ 'exclude' => $exclude,
+ 'showfullpath' => $showfullpath,
+ 'orderBy' => $orderBy
+ );
+
+ $reshook = $hookmanager->executeHooks('selectWorkstations', $parameters, $this);
+ if ($reshook > 0) {
+ $out = $hookmanager->resPrint;
+ } elseif ($reshook == 0) {
+ $out .= $hookmanager->resPrint;
+ }
+
+ return $out;
+ }
+
/**
* Display form to select warehouse
*
diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php
index c8cef2abe34..69e1f0c8357 100644
--- a/htdocs/product/class/product.class.php
+++ b/htdocs/product/class/product.class.php
@@ -238,6 +238,11 @@ class Product extends CommonObject
*/
public $duration_value;
+ /*
+ * Service Workstation
+ */
+ public $fk_default_workstation;
+
/**
* Exoiration unit
*/
@@ -1146,6 +1151,7 @@ class Product extends CommonObject
$sql .= ", volume = ".($this->volume != '' ? "'".$this->db->escape($this->volume)."'" : 'null');
$sql .= ", volume_units = ".($this->volume_units != '' ? "'".$this->db->escape($this->volume_units)."'" : 'null');
$sql .= ", fk_default_warehouse = ".($this->fk_default_warehouse > 0 ? $this->db->escape($this->fk_default_warehouse) : 'null');
+ $sql .= ", fk_default_workstation = ".($this->fk_default_workstation > 0 ? $this->db->escape($this->fk_default_workstation) : 'null');
$sql .= ", seuil_stock_alerte = ".((isset($this->seuil_stock_alerte) && is_numeric($this->seuil_stock_alerte)) ? (float) $this->seuil_stock_alerte : 'null');
$sql .= ", description = '".$this->db->escape($this->description)."'";
$sql .= ", url = ".($this->url ? "'".$this->db->escape($this->url)."'" : 'null');
@@ -2287,7 +2293,7 @@ class Product extends CommonObject
$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,";
$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,";
- $sql .= " p.tobuy, p.fk_product_type, p.duration, p.fk_default_warehouse, p.seuil_stock_alerte, p.canvas, p.net_measure, p.net_measure_units, p.weight, p.weight_units,";
+ $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,";
$sql .= " p.length, p.length_units, p.width, p.width_units, p.height, p.height_units,";
$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,";
if (empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) {
@@ -2349,7 +2355,7 @@ class Product extends CommonObject
if ($separatedStock) {
$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,";
$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,";
- $sql .= " p.tobuy, p.fk_product_type, p.duration, p.fk_default_warehouse, p.seuil_stock_alerte, p.canvas, p.net_measure, p.net_measure_units, p.weight, p.weight_units,";
+ $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,";
$sql .= " p.length, p.length_units, p.width, p.width_units, p.height, p.height_units,";
$sql .= " p.surface, p.surface_units, p.volume, p.volume_units, p.barcode, p.fk_barcode_type, p.finished,";
if (empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) {
@@ -2448,6 +2454,7 @@ class Product extends CommonObject
$this->accountancy_code_sell_export = $obj->accountancy_code_sell_export;
$this->fk_default_warehouse = $obj->fk_default_warehouse;
+ $this->fk_default_workstation = $obj->fk_default_workstation;
$this->seuil_stock_alerte = $obj->seuil_stock_alerte;
$this->desiredstock = $obj->desiredstock;
$this->stock_reel = $obj->stock;