From 4edbd5c4e3ff7f1d1ae8d5742dd44a50086a5239 Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Tue, 25 Jan 2022 10:31:45 +0100 Subject: [PATCH 1/9] NEW : Creation of the function select_bom() used to display bom select list --- htdocs/bom/tpl/objectline_create.tpl.php | 2 +- htdocs/core/class/html.form.class.php | 51 ++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/htdocs/bom/tpl/objectline_create.tpl.php b/htdocs/bom/tpl/objectline_create.tpl.php index 7419c4618e0..0a3a3b34e7a 100644 --- a/htdocs/bom/tpl/objectline_create.tpl.php +++ b/htdocs/bom/tpl/objectline_create.tpl.php @@ -109,7 +109,7 @@ if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { if (!empty($conf->global->BOM_SUB_BOM)) { print '
'.$langs->trans("or").'
'.$langs->trans("BOM"); // TODO Add component to select a BOM - print ''; + $form->select_bom(); } print ''; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 88fca7b536a..fe47047150d 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -2362,6 +2362,57 @@ class Form } } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + + /** + * Return list of BOM for customer in Ajax if Ajax activated or go to select_produits_list + * + * @param int $selected Preselected BOM id + * @param string $htmlname Name of HTML select field (must be unique in page). + * @param int $limit Limit on number of returned lines + * @param int $status Sell status -1=Return all bom, 0=Draft BOM, 1=Validated BOM + * @param int $type type of the BOM (-1=Return all BOM, 0=Return disassemble BOM, 1=Return manufacturing BOM) + * @param string $showempty '' to not show empty line. Translation key to show an empty line. '1' show empty line with no text. + * @param string $morecss Add more css on select + * @return void|string + */ + public function select_bom($selected = '', $htmlname = 'bom_id', $limit = 0, $status = 1, $type = 1, $showempty = '1', $morecss = '', $nooutput = '') + { + // phpcs:enable + global $conf, $user, $langs, $db; + $error = 0; + $out = ''; + + $out .= ''; - $sql = 'SELECT b.rowid, b.ref, b.label'; + $sql = 'SELECT b.rowid, b.ref, b.label, b.fk_product'; $sql.= ' FROM '.MAIN_DB_PREFIX.'bom_bom as b'; - $sql .= ' WHERE b.entity IN ('.getEntity('bom').')'; - if(!empty($status)) $sql.= ' AND status = '.$status; - if(!empty($type)) $sql.= ' AND status = '. $type; + $sql.= ' WHERE b.entity IN ('.getEntity('bom').')'; + if(!empty($status)) $sql.= ' AND status = '. (int) $status; + if(!empty($type)) $sql.= ' AND status = '. (int) $type; if(!empty($limit)) $sql.= 'LIMIT '. (int) $limit; $resql = $db->query($sql); if($resql){ @@ -2399,8 +2407,10 @@ class Form $out .= '> '; } while ($obj = $db->fetch_object($resql)){ - if($obj->rowid == $selected) $out .= ''; - $out .= ''; + $product = new Product($db); + $res = $product->fetch($obj->fk_product); + if($obj->rowid == $selected) $out .= ''; + $out .= ''; } } else { $error++; From f37c04bc2f7ab59c407c261b27b03a92c25357f5 Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Tue, 25 Jan 2022 12:06:40 +0100 Subject: [PATCH 3/9] NEW : Add the possibility to add sub-BOMs to BOM --- htdocs/bom/bom_card.php | 15 ++++++++++++--- htdocs/bom/tpl/objectline_view.tpl.php | 7 ------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/htdocs/bom/bom_card.php b/htdocs/bom/bom_card.php index 748aea4ddb2..26764072956 100644 --- a/htdocs/bom/bom_card.php +++ b/htdocs/bom/bom_card.php @@ -148,8 +148,17 @@ if (empty($reshook)) { $error = 0; // Set if we used free entry or predefined product - $idprod = (int) GETPOST('idprod', 'int'); - $bom_child = (int) GETPOST('bom_select', 'int'); + $bom_child_id = (int) GETPOST('bom_id', 'int'); + if($bom_child_id > 0){ + $bom_child = new BOM($db); + $res = $bom_child->fetch($bom_child_id); + if($res){ + $idprod = $bom_child->fk_product; + } + } else { + $idprod = (int) GETPOST('idprod', 'int'); + } + $qty = price2num(GETPOST('qty', 'alpha'), 'MS'); $qty_frozen = price2num(GETPOST('qty_frozen', 'alpha'), 'MS'); $disable_stock_change = GETPOST('disable_stock_change', 'int'); @@ -173,7 +182,7 @@ if (empty($reshook)) { $bomline = new BOMLine($db); $bomline->fk_bom = $id; $bomline->fk_product = $idprod; - $bomline->fk_bom_child = $bom_child; + $bomline->fk_bom_child = $bom_child_id; $bomline->qty = $qty; $bomline->qty_frozen = (int) $qty_frozen; $bomline->disable_stock_change = (int) $disable_stock_change; diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php index 82626c12fec..f62143188eb 100644 --- a/htdocs/bom/tpl/objectline_view.tpl.php +++ b/htdocs/bom/tpl/objectline_view.tpl.php @@ -202,13 +202,6 @@ if ($resql) { // Product print ''.$sub_bom_product->getNomUrl(1).''; - // Sub-BOM - if ($sub_bom_line->fk_bom_child > 0) { - print ''.$sub_bom->getNomUrl(1).''; - } else { - print ' '; - } - // Qty print ''.price($sub_bom_line->qty * $line->qty, 0, '', 0, 0).''; if ($sub_bom_line->qty_frozen > 0) { From 08d830f4501c959129d8b48156f73bec23659478 Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Tue, 25 Jan 2022 16:40:28 +0100 Subject: [PATCH 4/9] FIX : Fixing total_cost, qty_frozen and display problems --- htdocs/bom/tpl/objectline_view.tpl.php | 36 +++++++++++++++++++------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php index f62143188eb..0c74cee43ce 100644 --- a/htdocs/bom/tpl/objectline_view.tpl.php +++ b/htdocs/bom/tpl/objectline_view.tpl.php @@ -41,7 +41,7 @@ if (empty($object) || !is_object($object)) { } -global $forceall, $senderissupplier, $inputalsopricewithtax, $outputalsopricetotalwithtax; +global $forceall, $senderissupplier, $inputalsopricewithtax, $outputalsopricetotalwithtax, $langs; if (empty($dateSelector)) { $dateSelector = 0; @@ -83,8 +83,10 @@ $tmpproduct->fetch($line->fk_product); $tmpbom = new BOM($object->db); $res = $tmpbom->fetch($line->fk_bom_child); if ($tmpbom->id > 0) { - print $tmpbom->getNomUrl(1); print '' . (empty($conf->global->BOM_SHOW_ALL_BOM_BY_DEFAULT) ? '(+)' : '(-)') . ' '; + print $tmpproduct->getNomUrl(1); + print ' '.$langs->trans('OR').' '; + print $tmpbom->getNomUrl(1); } else { print $tmpproduct->getNomUrl(1); print ' - '.$tmpproduct->label; @@ -176,7 +178,7 @@ if ($action == 'selectlines') { print ''; // Select of all the sub-BOM lines -$sql = 'SELECT rowid, fk_bom_child, fk_product FROM '.MAIN_DB_PREFIX.'bom_bomline AS bl'; +$sql = 'SELECT rowid, fk_bom_child, fk_product, qty FROM '.MAIN_DB_PREFIX.'bom_bomline AS bl'; $sql.= ' WHERE fk_bom ='. (int) $tmpbom->id; $resql = $object->db->query($sql); @@ -199,14 +201,23 @@ if ($resql) { print ''; } - // Product - print ''.$sub_bom_product->getNomUrl(1).''; + // Product OR BOM + print ''; + if(!empty($obj->fk_bom_child)){ + print $sub_bom_product->getNomUrl(1); + print ' '.$langs->trans('OR').' '; + print $sub_bom->getNomUrl(1); + } else { + print $sub_bom_product->getNomUrl(1); + print ''; + } // Qty - print ''.price($sub_bom_line->qty * $line->qty, 0, '', 0, 0).''; if ($sub_bom_line->qty_frozen > 0) { - print ''.$sub_bom_line->qty_frozen.''; + print ''.price($sub_bom_line->qty, 0, '', 0, 0).''; + print ''.$langs->trans('Yes').''; } else { + print ''.price($sub_bom_line->qty * $line->qty, 0, '', 0, 0).''; print ' '; } @@ -221,9 +232,16 @@ if ($resql) { print ''.$sub_bom_line->efficiency.''; // Cost price if it's defined - if ($sub_bom_product->cost_price > 0) { + if (!empty($obj->fk_bom_child)) { + $bom = new BOM($object->db); + $bom->fetch($obj->fk_bom_child); + $bom->calculateCosts(); + $bom->total_cost * $line->qty; + print ''.price($bom->total_cost * $line->qty).''; + $total_cost+= $bom->total_cost * $line->qty; + } elseif ($sub_bom_product->cost_price > 0) { print ''.price($sub_bom_product->cost_price * $line->qty).''; - $total_cost.= $sub_bom_product->cost_price * $line->qty; + $total_cost+= $sub_bom_product->cost_price * $line->qty; } elseif ($sub_bom_product->pmp > 0) { // PMP if cost price isn't defined print ''.price($sub_bom_product->pmp * $line->qty).''; $total_cost.= $sub_bom_product->pmp * $line->qty; From 36068d4279375d8b813d097f9deecd998babecb3 Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Wed, 26 Jan 2022 14:41:36 +0100 Subject: [PATCH 5/9] FIX : Fixing total errors --- htdocs/bom/class/bom.class.php | 41 ++++++++++++++++++-------- htdocs/bom/tpl/objectline_view.tpl.php | 17 ++++------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php index 0520c76dde2..6f170fb066b 100644 --- a/htdocs/bom/class/bom.class.php +++ b/htdocs/bom/class/bom.class.php @@ -1064,26 +1064,41 @@ class BOM extends CommonObject $tmpproduct->cost_price = 0; $tmpproduct->pmp = 0; - $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(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; + } + } + + $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(); + $this->total_cost += $bom_child->total_cost; + } else { + $this->error = $bom_child->error; + return -2; } } - $line->total_cost = price2num($line->qty * $line->unit_cost, 'MT'); - - $this->total_cost += $line->total_cost; } $this->total_cost = price2num($this->total_cost, 'MT'); - if ($this->qty) { + if ($this->qty > 0) { $this->unit_cost = price2num($this->total_cost / $this->qty, 'MU'); + } elseif ($this->qty < 0) { + $this->unit_cost = price2num($this->total_cost * $this->qty, 'MU'); } } } diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php index 0c74cee43ce..fc40c8a54f2 100644 --- a/htdocs/bom/tpl/objectline_view.tpl.php +++ b/htdocs/bom/tpl/objectline_view.tpl.php @@ -232,27 +232,22 @@ if ($resql) { print ''.$sub_bom_line->efficiency.''; // Cost price if it's defined - if (!empty($obj->fk_bom_child)) { - $bom = new BOM($object->db); - $bom->fetch($obj->fk_bom_child); - $bom->calculateCosts(); - $bom->total_cost * $line->qty; - print ''.price($bom->total_cost * $line->qty).''; - $total_cost+= $bom->total_cost * $line->qty; - } elseif ($sub_bom_product->cost_price > 0) { + if ($sub_bom_product->cost_price > 0) { print ''.price($sub_bom_product->cost_price * $line->qty).''; $total_cost+= $sub_bom_product->cost_price * $line->qty; } elseif ($sub_bom_product->pmp > 0) { // PMP if cost price isn't defined print ''.price($sub_bom_product->pmp * $line->qty).''; $total_cost.= $sub_bom_product->pmp * $line->qty; } else { // Minimum purchase price if cost price and PMP aren't defined - $sql_supplier_price = 'SELECT MIN(price) AS min_price FROM '.MAIN_DB_PREFIX.'product_fournisseur_price'; + $sql_supplier_price = 'SELECT MIN(price) AS min_price, quantity AS qty FROM '.MAIN_DB_PREFIX.'product_fournisseur_price'; $sql_supplier_price.= ' WHERE fk_product = '. (int) $sub_bom_product->id; $resql_supplier_price = $object->db->query($sql_supplier_price); if ($resql_supplier_price) { $obj = $object->db->fetch_object($resql_supplier_price); - print ''.price($obj->min_price * $line->qty).''; - $total_cost+= $obj->min_price * $line->qty; + $line_cost = $obj->min_price/$obj->qty * $sub_bom_line->qty; + + print ''.price($line_cost).''; + $total_cost+= $line_cost; } } From 6d3066a312b802ba92d7606e6c432d01f42db21b Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Wed, 26 Jan 2022 14:46:45 +0100 Subject: [PATCH 6/9] FIX : Fixing trads --- htdocs/bom/tpl/objectline_view.tpl.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php index fc40c8a54f2..e8550e9d6b6 100644 --- a/htdocs/bom/tpl/objectline_view.tpl.php +++ b/htdocs/bom/tpl/objectline_view.tpl.php @@ -85,7 +85,7 @@ $res = $tmpbom->fetch($line->fk_bom_child); if ($tmpbom->id > 0) { print '' . (empty($conf->global->BOM_SHOW_ALL_BOM_BY_DEFAULT) ? '(+)' : '(-)') . ' '; print $tmpproduct->getNomUrl(1); - print ' '.$langs->trans('OR').' '; + print ' '.$langs->trans('or').' '; print $tmpbom->getNomUrl(1); } else { print $tmpproduct->getNomUrl(1); @@ -205,7 +205,7 @@ if ($resql) { print ''; if(!empty($obj->fk_bom_child)){ print $sub_bom_product->getNomUrl(1); - print ' '.$langs->trans('OR').' '; + print ' '.$langs->trans('or').' '; print $sub_bom->getNomUrl(1); } else { print $sub_bom_product->getNomUrl(1); From 9342fa8781b6df278054e6d92acf08696a88734c Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Wed, 26 Jan 2022 14:15:53 +0000 Subject: [PATCH 7/9] Fixing style errors. --- htdocs/bom/bom_card.php | 14 +++++++------- htdocs/bom/class/bom.class.php | 4 ++-- htdocs/bom/tpl/objectline_view.tpl.php | 16 ++++++++-------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/htdocs/bom/bom_card.php b/htdocs/bom/bom_card.php index 26764072956..d31e21e635b 100644 --- a/htdocs/bom/bom_card.php +++ b/htdocs/bom/bom_card.php @@ -149,13 +149,13 @@ if (empty($reshook)) { // Set if we used free entry or predefined product $bom_child_id = (int) GETPOST('bom_id', 'int'); - if($bom_child_id > 0){ - $bom_child = new BOM($db); - $res = $bom_child->fetch($bom_child_id); - if($res){ - $idprod = $bom_child->fk_product; - } - } else { + if ($bom_child_id > 0) { + $bom_child = new BOM($db); + $res = $bom_child->fetch($bom_child_id); + if ($res) { + $idprod = $bom_child->fk_product; + } + } else { $idprod = (int) GETPOST('idprod', 'int'); } diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php index 6f170fb066b..4923e9d0ca2 100644 --- a/htdocs/bom/class/bom.class.php +++ b/htdocs/bom/class/bom.class.php @@ -1064,7 +1064,7 @@ class BOM extends CommonObject $tmpproduct->cost_price = 0; $tmpproduct->pmp = 0; - if(empty($line->fk_bom_child)){ + 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; @@ -1083,7 +1083,7 @@ class BOM extends CommonObject } else { $bom_child= new BOM($this->db); $res = $bom_child->fetch($line->fk_bom_child); - if($res>0){ + if ($res>0) { $bom_child->calculateCosts(); $this->total_cost += $bom_child->total_cost; } else { diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php index e8550e9d6b6..4360d521036 100644 --- a/htdocs/bom/tpl/objectline_view.tpl.php +++ b/htdocs/bom/tpl/objectline_view.tpl.php @@ -85,8 +85,8 @@ $res = $tmpbom->fetch($line->fk_bom_child); if ($tmpbom->id > 0) { print '' . (empty($conf->global->BOM_SHOW_ALL_BOM_BY_DEFAULT) ? '(+)' : '(-)') . ' '; print $tmpproduct->getNomUrl(1); - print ' '.$langs->trans('or').' '; - print $tmpbom->getNomUrl(1); + print ' '.$langs->trans('or').' '; + print $tmpbom->getNomUrl(1); } else { print $tmpproduct->getNomUrl(1); print ' - '.$tmpproduct->label; @@ -203,14 +203,14 @@ if ($resql) { // Product OR BOM print ''; - if(!empty($obj->fk_bom_child)){ + if (!empty($obj->fk_bom_child)) { print $sub_bom_product->getNomUrl(1); print ' '.$langs->trans('or').' '; print $sub_bom->getNomUrl(1); - } else { + } else { print $sub_bom_product->getNomUrl(1); - print ''; - } + print ''; + } // Qty if ($sub_bom_line->qty_frozen > 0) { @@ -232,7 +232,7 @@ if ($resql) { print ''.$sub_bom_line->efficiency.''; // Cost price if it's defined - if ($sub_bom_product->cost_price > 0) { + if ($sub_bom_product->cost_price > 0) { print ''.price($sub_bom_product->cost_price * $line->qty).''; $total_cost+= $sub_bom_product->cost_price * $line->qty; } elseif ($sub_bom_product->pmp > 0) { // PMP if cost price isn't defined @@ -244,7 +244,7 @@ if ($resql) { $resql_supplier_price = $object->db->query($sql_supplier_price); if ($resql_supplier_price) { $obj = $object->db->fetch_object($resql_supplier_price); - $line_cost = $obj->min_price/$obj->qty * $sub_bom_line->qty; + $line_cost = $obj->min_price/$obj->qty * $sub_bom_line->qty; print ''.price($line_cost).''; $total_cost+= $line_cost; From d38ff3ad9b6fc60a672f08aea834265cccc54e1d Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Wed, 26 Jan 2022 15:53:30 +0100 Subject: [PATCH 8/9] FIX : Fixing stickler returns --- htdocs/core/class/html.form.class.php | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index e7fd8d27967..caf20ffcbad 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -2374,6 +2374,8 @@ class Form * @param int $type type of the BOM (-1=Return all BOM, 0=Return disassemble BOM, 1=Return manufacturing BOM) * @param string $showempty '' to not show empty line. Translation key to show an empty line. '1' show empty line with no text. * @param string $morecss Add more css on select + * @param string $nooutput + * @param string $forcecombo * @return void|string */ public function select_bom($selected = '', $htmlname = 'bom_id', $limit = 0, $status = 1, $type = 1, $showempty = '1', $morecss = '', $nooutput = '', $forcecombo = 0) @@ -2396,20 +2398,20 @@ class Form $sql = 'SELECT b.rowid, b.ref, b.label, b.fk_product'; $sql.= ' FROM '.MAIN_DB_PREFIX.'bom_bom as b'; $sql.= ' WHERE b.entity IN ('.getEntity('bom').')'; - if(!empty($status)) $sql.= ' AND status = '. (int) $status; - if(!empty($type)) $sql.= ' AND status = '. (int) $type; - if(!empty($limit)) $sql.= 'LIMIT '. (int) $limit; + if (!empty($status)) $sql.= ' AND status = '. (int) $status; + if (!empty($type)) $sql.= ' AND status = '. (int) $type; + if (!empty($limit)) $sql.= 'LIMIT '. (int) $limit; $resql = $db->query($sql); - if($resql){ + if ($resql) { if ($showempty) { $out .= ''; + if ($obj->rowid == $selected) $out .= ''; $out .= ''; } } else { From e52fb89182ce2b22a992015860859fbe1142e128 Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Wed, 26 Jan 2022 16:36:58 +0100 Subject: [PATCH 9/9] FIX : Fixing stickler returns --- htdocs/core/class/html.form.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index caf20ffcbad..6c4c3b411b8 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -2374,8 +2374,8 @@ class Form * @param int $type type of the BOM (-1=Return all BOM, 0=Return disassemble BOM, 1=Return manufacturing BOM) * @param string $showempty '' to not show empty line. Translation key to show an empty line. '1' show empty line with no text. * @param string $morecss Add more css on select - * @param string $nooutput - * @param string $forcecombo + * @param string $nooutput No print, return the output into a string + * @param int $forcecombo Force to use combo box * @return void|string */ public function select_bom($selected = '', $htmlname = 'bom_id', $limit = 0, $status = 1, $type = 1, $showempty = '1', $morecss = '', $nooutput = '', $forcecombo = 0)