Merge pull request #19935 from atm-adrien/NEW_SUB_BOM_develop

NEW : Sub-bom
This commit is contained in:
Laurent Destailleur 2022-01-28 19:01:30 +01:00 committed by GitHub
commit d72538506f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 126 additions and 33 deletions

View File

@ -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;

View File

@ -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');
}
}
}

View File

@ -109,7 +109,7 @@ if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) {
if (!empty($conf->global->BOM_SUB_BOM)) {
print '<br><span class="opacitymedium">'.$langs->trans("or").'</span><br>'.$langs->trans("BOM");
// TODO Add component to select a BOM
print '<select id="bom_select" name="bom_select"><option value="-1">TODO</option></select>';
$form->select_bom();
}
print '</td>';

View File

@ -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 '<a class="collapse_bom" id="collapse-'.$line->id.'" href="#">' . (empty($conf->global->BOM_SHOW_ALL_BOM_BY_DEFAULT) ? '(+)' : '(-)') . '&nbsp;</a>';
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 '</tr>';
// 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,21 +201,23 @@ if ($resql) {
print '<tr class="sub_bom_lines" parentid="'.$line->id.'">';
}
// Product
print '<td style="padding-left: 5%" id="sub_bom_product_'.$sub_bom_line->id.'">'.$sub_bom_product->getNomUrl(1).'</td>';
// Sub-BOM
if ($sub_bom_line->fk_bom_child > 0) {
print '<td id="sub_bom_bom_'.$sub_bom_line->id.'">'.$sub_bom->getNomUrl(1).'</td>';
// Product OR BOM
print '<td style="padding-left: 5%" id="sub_bom_product_'.$sub_bom_line->id.'">';
if (!empty($obj->fk_bom_child)) {
print $sub_bom_product->getNomUrl(1);
print ' '.$langs->trans('or').' ';
print $sub_bom->getNomUrl(1);
} else {
print '<td id="sub_bom_bom_'.$sub_bom_line->id.'">&nbsp;</td>';
print $sub_bom_product->getNomUrl(1);
print '</td>';
}
// Qty
print '<td class="linecolqty nowrap right" id="sub_bom_qty_'.$sub_bom_line->id.'">'.price($sub_bom_line->qty * $line->qty, 0, '', 0, 0).'</td>';
if ($sub_bom_line->qty_frozen > 0) {
print '<td class="linecolqtyfrozen nowrap right" id="sub_bom_qty_frozen_'.$sub_bom_line->id.'">'.$sub_bom_line->qty_frozen.'</td>';
print '<td class="linecolqty nowrap right" id="sub_bom_qty_'.$sub_bom_line->id.'">'.price($sub_bom_line->qty, 0, '', 0, 0).'</td>';
print '<td class="linecolqtyfrozen nowrap right" id="sub_bom_qty_frozen_'.$sub_bom_line->id.'">'.$langs->trans('Yes').'</td>';
} else {
print '<td class="linecolqty nowrap right" id="sub_bom_qty_'.$sub_bom_line->id.'">'.price($sub_bom_line->qty * $line->qty, 0, '', 0, 0).'</td>';
print '<td class="linecolqtyfrozen nowrap right" id="sub_bom_qty_frozen_'.$sub_bom_line->id.'">&nbsp;</td>';
}
@ -230,18 +234,20 @@ if ($resql) {
// Cost price if it's defined
if ($sub_bom_product->cost_price > 0) {
print '<td class="linecolcost nowrap right" id="sub_bom_cost_'.$sub_bom_line->id.'">'.price($sub_bom_product->cost_price * $line->qty).'</td>';
$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 '<td class="linecolcost nowrap right" id="sub_bom_cost_'.$sub_bom_line->id.'">'.price($sub_bom_product->pmp * $line->qty).'</td>';
$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 '<td class="linecolcost nowrap right" id="sub_bom_cost_'.$sub_bom_line->id.'">'.price($obj->min_price * $line->qty).'</td>';
$total_cost+= $obj->min_price * $line->qty;
$line_cost = $obj->min_price/$obj->qty * $sub_bom_line->qty;
print '<td class="linecolcost nowrap right" id="sub_bom_cost_'.$sub_bom_line->id.'">'.price($line_cost).'</td>';
$total_cost+= $line_cost;
}
}

View File

@ -2367,6 +2367,69 @@ 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
* @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)
{
// phpcs:enable
global $conf, $user, $langs, $db;
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
$error = 0;
$out = '';
if (!$forcecombo) {
include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
$out .= ajax_combobox($htmlname, $events, getDolGlobalInt("PRODUIT_USE_SEARCH_TO_SELECT"));
}
$out .= '<select class="flat'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.'" id="'.$htmlname.'">';
$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;
$resql = $db->query($sql);
if ($resql) {
if ($showempty) {
$out .= '<option value="-1"';
if (empty($selected)) $out .= ' selected';
$out .= '>&nbsp;</option>';
}
while ($obj = $db->fetch_object($resql)) {
$product = new Product($db);
$res = $product->fetch($obj->fk_product);
if ($obj->rowid == $selected) $out .= '<option value="'.$obj->rowid.'" selected>'.$obj->ref.' - '. $product->label .' - '.$obj->label.'</option>';
$out .= '<option value="'.$obj->rowid.'">'.$obj->ref.' - '.$product->label .' - '. $obj->label.'</option>';
}
} else {
$error++;
dol_print_error($db);
}
if (empty($nooutput)) {
print $out;
} else {
return $out;
}
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Return list of products for a customer.