diff --git a/htdocs/bom/bom_card.php b/htdocs/bom/bom_card.php
index ee619a589e3..759c313cd3c 100644
--- a/htdocs/bom/bom_card.php
+++ b/htdocs/bom/bom_card.php
@@ -34,6 +34,8 @@ require_once DOL_DOCUMENT_ROOT.'/mrp/lib/mrp.lib.php';
// Load translation files required by the page
$langs->loadLangs(array("mrp", "other"));
+global $filtertype;
+
// Get parameters
$id = GETPOST('id', 'int');
$ref = GETPOST('ref', 'alpha');
@@ -541,50 +543,114 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
* Lines
*/
+
if (!empty($object->table_element_line)) {
- print '
\n";
-
- mrpCollapseBomManagement();
}
diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php
index 598c4c73945..f1c5803311b 100644
--- a/htdocs/bom/class/bom.class.php
+++ b/htdocs/bom/class/bom.class.php
@@ -23,6 +23,7 @@
// 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 . '/societe/class/societe.class.php';
//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
@@ -399,6 +400,56 @@ class BOM extends CommonObject
return $result;
}
+ /**
+ * Load object lines in memory from the database
+ *
+ * @return int <0 if KO, 0 if not found, >0 if OK
+ */
+ public function fetchLinesbytype($type = 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 = ". $type;
+ 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 1;
+ } else {
+ $this->error = $this->db->lasterror();
+ $this->errors[] = $this->error;
+ return -1;
+ }
+ }
+
+
/**
* Load list of objects in memory from the database.
*
@@ -1044,6 +1095,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;
@@ -1056,38 +1109,54 @@ 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;
}
}
-
- $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;
+ if(!($conf->workstation->enabled)) {
+ $line->total_cost = price2num($line->qty * $tmpproduct->cost_price, 'MT');
} else {
- $this->error = $bom_child->error;
- return -2;
+
+ if($tmpproduct->fk_default_workstation){
+ $workstation = new Workstation($this->db);
+ $workstation->fetch($tmpproduct->fk_default_workstation);
+
+ $line->total_cost = price2num($line->qty * $workstation->thm_operator_estimated, 'MT');
+ }
}
+ $this->total_cost += $line->total_cost;
}
}
$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) {
diff --git a/htdocs/bom/tpl/objectline_create.tpl.php b/htdocs/bom/tpl/objectline_create.tpl.php
index 0a3a3b34e7a..82154dcb078 100644
--- a/htdocs/bom/tpl/objectline_create.tpl.php
+++ b/htdocs/bom/tpl/objectline_create.tpl.php
@@ -36,12 +36,17 @@ 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;
+}
+
// Define colspan for the button 'Add'
$colspan = 3; // Columns: total ht + col edit + col delete
@@ -53,6 +58,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 +68,25 @@ 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')) . ' ';
}
- 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 ' ';
+ else {
+ print '' . $form->textwithpicto($langs->trans('Unit'), '').' ';
+ if($conf->workstation->enabled) print '' . $form->textwithpicto($langs->trans('Workstation'), '') . ' ';
+ print '' . $form->textwithpicto($langs->trans('TotalCost'), '') . ' ';
+ }
+
+ print ' ';
print ' ';
}
print '';
@@ -88,14 +103,14 @@ print '';
// Predefined product/service
if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) {
- 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
@@ -106,7 +121,7 @@ if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) {
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,53 @@ $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++;
+ print '';
+ print ' ';
+ 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');
diff --git a/htdocs/bom/tpl/objectline_edit.tpl.php b/htdocs/bom/tpl/objectline_edit.tpl.php
index e5f24fa994f..7812c2fcc16 100644
--- a/htdocs/bom/tpl/objectline_edit.tpl.php
+++ b/htdocs/bom/tpl/objectline_edit.tpl.php
@@ -38,12 +38,14 @@ if (empty($object) || !is_object($object)) {
}
-global $forceall;
+global $forceall, $filtertype;
if (empty($forceall)) {
$forceall = 0;
}
+if(empty($filtertype)) $filtertype = 0;
+
// Define colspan for the button 'Add'
$colspan = 3; // Columns: total ht + col edit + col delete
@@ -108,28 +110,47 @@ 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 ' ';
+
+ $coldisplay++;
+ print '';
+ 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..498002cc50c 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";
@@ -62,22 +66,31 @@ print ' ';
// Qty
print ''.$form->textwithpicto($langs->trans('Qty'), $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")).' ';
+ print '' . $form->textwithpicto($langs->trans('QtyFrozen'), $langs->trans("QuantityConsumedInvariable")) . ' ';
// Disable stock change
-print ''.$form->textwithpicto($langs->trans('DisableStockChange'), $langs->trans('DisableStockChangeHelp')).' ';
+ print '' . $form->textwithpicto($langs->trans('DisableStockChange'), $langs->trans('DisableStockChangeHelp')) . ' ';
// Efficiency
-print ''.$form->textwithpicto($langs->trans('ManufacturingEfficiency'), $langs->trans('ValueOfMeansLoss')).' ';
+ 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'), '') . ' ';
+}
// Cost
print ''.$form->textwithpicto($langs->trans("TotalCost"), $langs->trans("BOMTotalCost")).' ';
+
print ' '; // No width to allow autodim
print ' ';
diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php
index 61b394a3b0f..dee6bdbde60 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;
@@ -100,29 +105,50 @@ $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 {
+ $product = new Product($object->db);
+ $res = $product->fetch($line->fk_product);
+
+ //Unité
+ print '';
+ $coldisplay++;
+ echo $product->duration_unit;
+ print ' ';
+
+ //Poste de travail
+ if($conf->workstation->enabled) {
+ $workstation = new Workstation($object->db);
+ $workstation->fetch($product->fk_default_workstation);
+
+ print '';
+ $coldisplay++;
+ 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/langs/fr_FR/mrp.lang b/htdocs/langs/fr_FR/mrp.lang
index 6211db86e72..f952be1100a 100644
--- a/htdocs/langs/fr_FR/mrp.lang
+++ b/htdocs/langs/fr_FR/mrp.lang
@@ -82,6 +82,8 @@ 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)
+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