From e90640594d0fa7b3af0208a263d60708c69576c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zieli=C5=84ski?= Date: Tue, 29 Jul 2025 12:55:27 +0200 Subject: [PATCH] ProductionPlanning - new way raw materials --- .../productsBySales/productsBySales.js | 43 +++-- .../productsBySales/productsBySales.php | 175 +++++++++++++++--- 2 files changed, 174 insertions(+), 44 deletions(-) diff --git a/modules/EcmReports/BimIT-Reports/productsBySales/productsBySales.js b/modules/EcmReports/BimIT-Reports/productsBySales/productsBySales.js index e1c9eaf8..34e18684 100644 --- a/modules/EcmReports/BimIT-Reports/productsBySales/productsBySales.js +++ b/modules/EcmReports/BimIT-Reports/productsBySales/productsBySales.js @@ -132,6 +132,7 @@ function SetTab(tab_name) { tabs[i].getElementsByTagName('a')[0].className = ''; } } + var prevTabId = SelectedTab; var prev = document.getElementById(SelectedTab); var curr = document.getElementById(tab_name); prev.style.display = 'none'; @@ -142,7 +143,7 @@ function SetTab(tab_name) { $("#toogleReadyProducts").val("Ukryj gotowe"); $("#toogleServices").val("Ukryj usługi"); if (SelectedTab == '3') { - getRawMaterials(); + getRawMaterials(prevTabId); $("#toogleReadyProducts").show(); $("#toogleServices").show(); } @@ -258,25 +259,33 @@ function filterComponents() { drawComponents(filtered); updateComponentsPositions(); } -function getRawMaterials() { +function getRawMaterials(previousTab) { var ids = []; - $('input.allCheck:checkbox:checked').each(function () { - ids.push($(this).val()); - }); + if (previousTab === '1') { + $('input.allCheck:checkbox:checked').each(function () { + ids.push($(this).val()); + }); + } + if (previousTab === '2') { + $('input.componentCheck:checkbox:checked').each(function () { + ids.push($(this).val()); + }); + var tmp = []; + ids.forEach(el => { + var qty = parseFloat($("#qty-" + el).html().trim()); + var prod = {}; + prod.ecmproduct_id = el; + prod.quantity = qty; + tmp.push(prod); + }); + ids = tmp; + } if (ids.length === 0) { - alert('Wybierz pozycje zamówień'); - SetTab('1'); - return; - } - var cids = []; - $('input.componentCheck:checkbox:checked').each(function () { - cids.push($(this).val()); - }); - if (cids.length === 0) { - alert('Wybierz komponenty'); - SetTab('2'); + alert('Wybierz pozycje.'); + SetTab(previousTab); return; } + showLoader(); var url = $(location).attr('href') + "&to_pdf=1&ajaxAction=getRawMaterials"; @@ -285,7 +294,7 @@ function getRawMaterials() { url: url, data: { ids, - cids + type: previousTab === '1' ? 'sales' : 'components' }, success: function (data) { var result = JSON.parse(data); diff --git a/modules/EcmReports/BimIT-Reports/productsBySales/productsBySales.php b/modules/EcmReports/BimIT-Reports/productsBySales/productsBySales.php index 657ac5b1..f50c971b 100644 --- a/modules/EcmReports/BimIT-Reports/productsBySales/productsBySales.php +++ b/modules/EcmReports/BimIT-Reports/productsBySales/productsBySales.php @@ -109,7 +109,7 @@ if (!isset($_GET['ajaxAction'])) { } $orderTypes = []; - $res = $db->query("SELECT distinct s.type FROM ecmsales AS s WHERE s.delivery_date > '$dateFrom' $typesWhere"); + $res = $db->query("SELECT distinct s.type FROM ecmsales AS s WHERE s.delivery_date > '$dateFrom' $typesWhere"); while ($r = $db->fetchByAssoc($res)) { $orderTypes[] = $r['type']; } @@ -136,7 +136,7 @@ if (!isset($_GET['ajaxAction'])) { echo getComponents2($_POST['ids']); break; case 'getRawMaterials': - echo getRawMaterials($_POST['ids'], $_POST['cids']); + echo getRawMaterials2($_POST['ids'], $_POST['type']);; break; case 'saveProductDescription': saveProductDescription($_GET['itemId'], $_GET['description']); @@ -236,6 +236,104 @@ function getComponents($ids, $dateFrom, $dateTo) echo json_encode($componentsData); } +function getRawMaterials2($ids, $type) +{ + global $app_list_strings; + $db = $GLOBALS['db']; + $idsString = join("','", $ids); + $products = array(); + $response = array(); + if ($type == 'sales') { + $productsQuery = "SELECT si.ecmproduct_id, SUM(si.quantity) as quantity + FROM ecmsaleitems AS si + WHERE si.id IN ('" . $idsString . "')"; + $prows = $db->query($productsQuery); + while ($p = $db->fetchByAssoc($prows)) { + $prod = array(); + $prod['ecmproduct_id'] = $p['ecmproduct_id']; + $prod['quantity'] = $p['quantity']; + $products[] = $prod; + } + } else if ($type == 'components') { + $products = $ids; + } + + $grouppedProducts = array_reduce($products, function ($carry, $item) { + if (isset($carry[$item['ecmproduct_id']])) { + $carry[$item['ecmproduct_id']]['productQty'] += $item['quantity']; + } else { + $carry[$item['ecmproduct_id']] = $item; + } + return $carry; + }); + + $rawMaterialsData = array(); + + foreach ($grouppedProducts as $product) { + $rawMaterialsData = array_merge( + $rawMaterialsData, + getProductRawMaterials($product['ecmproduct_id'], $product['quantity']) + ); + } + + $grouppedRawMaterials = array_reduce($rawMaterialsData, function ($carry, $item) { + if (isset($carry[$item['ecmproduct_id']])) { + $carry[$item['ecmproduct_id']]['productQty'] += $item['quantity']; + } else { + $carry[$item['ecmproduct_id']] = $item; + } + return $carry; + }); + + foreach ($grouppedRawMaterials as $material) { + $product = $db->fetchByAssoc($db->query(" + SELECT p.id, p.code, p.name, p.group_ks, p.unit_id, p.ems_qty_in_stock as stockState + FROM ecmproducts AS p + WHERE p.id='" . $material['ecmproduct_id'] . "' + ")); + $ordered = $db->fetchByAssoc($db->query("SELECT SUM(poi.quantity) as ordered, GROUP_CONCAT(poi.ecmpurchaseorder_id SEPARATOR '|') AS orders + FROM ecmpurchaseorderitems as poi + INNER JOIN ecmpurchaseorders as po + ON poi.ecmpurchaseorder_id = po.id AND (po.status='registered' OR po.status='accepted') AND po.deleted=0 + WHERE poi.deleted=0 AND poi.ecmproduct_id = '" . $material['ecmproduct_id'] . "'")); + $orders = array(); + $ordersIds = explode('|', $ordered['orders']); + $ordersRes = $db->query("SELECT id, document_no, delivery_date FROM ecmpurchaseorders WHERE id IN ('" . join("','", $ordersIds) . "') ORDER BY date_entered DESC"); + while ($o = $db->fetchByAssoc($ordersRes)) { + $orders[] = array( + 'orderId' => $o['id'], + 'orderNr' => $o['document_no'], + 'orderDeliveryDate' => isset($o['delivery_date']) ? explode(' ', $o['delivery_date'])[0] : '' + ); + } + $vendor = $db->fetchByAssoc($db->query("SELECT d.parent_id, a.name + FROM ecmstockdocinitems AS i + INNER JOIN ecmstockdocins AS d + ON d.id = i.ecmstockdocin_id + INNER JOIN accounts AS a + ON a.id = d.parent_id + WHERE i.ecmproduct_id = '" . $material['ecmproduct_id'] . "' + ORDER BY d.register_date DESC + LIMIT 0,1")); + $row = array(); + $row['productId'] = $product['id']; + $row['productName'] = strlen($product['name']) > 55 ? substr($product['name'], 0, 55) . "..." : $product['name']; + $row['productFullName'] = $product['name']; + $row['productCode'] = strlen($product['code']) > 20 ? substr($product['code'], 0, 20) . "..." : $product['code']; + $row['productFullCode'] = $product['code']; + $row['productUnit'] = $app_list_strings['ecmproducts_unit_dom'][$product['unit_id']]; + $row['productOrdered'] = (!empty($ordered['ordered'])) ? $ordered['ordered'] : 0; + $row['productVendorName'] = $vendor ? $vendor['name'] : ''; + $row['productVendorId'] = $vendor ? $vendor['parent_id'] : ''; + $row['productQty'] = $material['quantity']; + $row['productGroupKS'] = $product['group_ks']; + $row['orders'] = $orders; + $row['productStockState'] = (!empty($product['stockState'])) ? $product['stockState'] : 0; + $response[] = $row; + } + return json_encode($response); +} + function getRawMaterials($ids, $cids) { $db = $GLOBALS['db']; @@ -306,7 +404,7 @@ function getRawMaterials($ids, $cids) } } } - + // group rawMaterialsData by productId and sum quantity and ordered $tmp = array_reduce($rawMaterialsData, function ($carry, $item) { if (isset($carry[$item['productId']])) { @@ -318,32 +416,47 @@ function getRawMaterials($ids, $cids) }, array()); // flat tmp array $rawMaterialsData = array_values($tmp); - + echo json_encode($rawMaterialsData); } + function getProductRawMaterials($productId, $quantity) { $db = $GLOBALS['db']; $response = array(); - $componentsQuery = "SELECT c.ecmcomponent_id, c.quantity - FROM ecmproductcomponents as c - WHERE c.ecmproduct_id = '$productId'"; - $crows = $db->query($componentsQuery); - if ($crows->num_rows == 0) { - return array( - array( - 'ecmproduct_id' => $productId, - 'quantity' => $quantity - ) - ); - } else { - while ($c = $db->fetchByAssoc($crows)) { - $response = array_merge($response, getProductRawMaterials($c['ecmcomponent_id'], $quantity * $c['quantity'])); + $rawMaterialsQuery = "SELECT + c.ecmcomponent_id, + c.quantity, + ( + SELECT COUNT(*) + FROM ecmproductcomponents as nested + WHERE nested.ecmproduct_id = c.ecmcomponent_id + ) as nested_components_count +FROM + ecmproductcomponents as c +WHERE + c.ecmproduct_id = '$productId'"; + + $rows = $db->query($rawMaterialsQuery); + + while ($r = $db->fetchByAssoc($rows)) { + if ($r['nested_components_count'] == 0) { + $response[] = array( + 'ecmproduct_id' => $r['ecmcomponent_id'], + 'quantity' => $r['quantity'] * $quantity + ); + } else { + $response = array_merge( + $response, + getProductRawMaterials($r['ecmcomponent_id'], $r['quantity'] * $quantity) + ); } - return $response; } + return $response; } -function addToProductionScheduler($orderItemId) { + +function addToProductionScheduler($orderItemId) +{ $db = $GLOBALS['db']; global $current_user; $saleInfo = $db->fetchByAssoc($db->query("SELECT quantity, ecmproduct_id, description, ecmsale_id FROM ecmsaleitems WHERE id ='$orderItemId'")); @@ -370,14 +483,18 @@ function addToProductionScheduler($orderItemId) { $db->query($query); } } -function addComponentToProductionScheduler($productId, $qty) { + +function addComponentToProductionScheduler($productId, $qty) +{ $db = $GLOBALS['db']; global $current_user; $query = sprintf("INSERT INTO productionScheduler VALUES ('%s', null, null, null, '%d', NOW(), NOW(), '%s', '%s', 0, '%s', 1, null, null);", generateUuidV4(), $qty, $current_user->id, $current_user->id, $productId); $db->query($query); } -function getComponents2($ids) { + +function getComponents2($ids) +{ $db = $GLOBALS['db']; global $app_list_strings; $idsString = join("','", $ids); @@ -457,7 +574,9 @@ function getComponents2($ids) { * */ } -function getProductComponents($productId, $quantity) { + +function getProductComponents($productId, $quantity) +{ $db = $GLOBALS['db']; $response = array(); $componentsQuery = "SELECT @@ -486,16 +605,18 @@ HAVING } else { // always add component to response $response[] = array( - 'ecmproduct_id' => $productId, - 'quantity' => $quantity + 'ecmproduct_id' => $productId, + 'quantity' => $quantity ); while ($c = $db->fetchByAssoc($crows)) { - $response = array_merge($response, getProductComponents($c['ecmcomponent_id'], $quantity * $c['quantity'])); + $response = array_merge($response, getProductComponents($c['ecmcomponent_id'], $quantity * $c['quantity'])); } return $response; } } -function generateUuidV4() { + +function generateUuidV4() +{ $data = openssl_random_pseudo_bytes(16); $data[6] = chr(ord($data[6]) & 0x0f | 0x40); $data[8] = chr(ord($data[8]) & 0x3f | 0x80);