Change 'Rack' to 'Bin'

This commit is contained in:
Thanakorn S
2026-05-27 17:14:53 +07:00
parent ea94b6a6ae
commit 987cf7ded9
41 changed files with 931 additions and 933 deletions
+35 -35
View File
@@ -12,7 +12,7 @@
* Dashboard reports → stats, movement charts, most moved, recent activity
* Warehouse detail → capacity, space used, balance, movement, trend, activity
* Expiry reports → expired / near-expiry stock
* Lot / Rack reports → lot stock log, product lots, rack log, rack occupancy
* Lot / Bin reports → lot stock log, product lots, bin log, bin occupancy
* Balance summary → getWarehouseBalanceSummary
*
* Security: All SQL uses PDO prepared statements with bound parameters.
@@ -159,25 +159,25 @@ class ReportManager
}
/**
* Total rack capacity (all racks across all warehouses) for this company.
* Total bin capacity (all bins across all warehouses) for this company.
* Used by the reports_stats dashboard tile.
*/
public function getTotalCapacity(): int
{
$sql = "SELECT COUNT(*)
FROM md_rack
FROM md_bin
WHERE company_id = :company_id";
return (int) $this->fetchScalar($sql);
}
/**
* Number of occupied racks (product_sku IS NOT NULL) for this company.
* Number of occupied bins (product_sku IS NOT NULL) for this company.
* Used by the reports_stats dashboard tile.
*/
public function getSpaceUsed(): int
{
$sql = "SELECT COUNT(*)
FROM md_rack
FROM md_bin
WHERE company_id = :company_id
AND product_sku IS NOT NULL";
return (int) $this->fetchScalar($sql);
@@ -710,15 +710,15 @@ class ReportManager
// ─────────────────────────────────────────────────────────────
/**
* Total rack capacity for a specific warehouse (all racks regardless of occupancy).
* Total bin capacity for a specific warehouse (all bins regardless of occupancy).
*
* @param int $warehouse_id The warehouse to query.
* @return int Total rack count.
* @return int Total bin count.
*/
public function getWarehouseCapacity(int $warehouse_id): int
{
$sth = $this->pdo->prepare(
"SELECT COUNT(*) FROM md_rack
"SELECT COUNT(*) FROM md_bin
WHERE company_id = :company_id AND warehouse = :warehouse_id"
);
$sth->execute([':company_id' => $this->companyId, ':warehouse_id' => $warehouse_id]);
@@ -726,15 +726,15 @@ class ReportManager
}
/**
* Number of occupied racks (product_sku IS NOT NULL) for a specific warehouse.
* Number of occupied bins (product_sku IS NOT NULL) for a specific warehouse.
*
* @param int $warehouse_id The warehouse to query.
* @return int Occupied rack count.
* @return int Occupied bin count.
*/
public function getWarehouseSpaceUsed(int $warehouse_id): int
{
$sth = $this->pdo->prepare(
"SELECT COUNT(*) FROM md_rack
"SELECT COUNT(*) FROM md_bin
WHERE company_id = :company_id AND warehouse = :warehouse_id
AND product_sku IS NOT NULL"
);
@@ -1008,14 +1008,14 @@ class ReportManager
s.lot_number,
s.zone,
s.aisle,
s.rack,
s.bin,
ROUND(SUM(s.`in`) - SUM(s.`out`), 2) AS quantity,
{$wh['id']} AS warehouse_id
FROM `{$table}` s
WHERE s.company_id = {$cid}
AND s.lot_number IS NOT NULL
AND s.status = 1
GROUP BY s.product_sku, s.lot_number, s.zone, s.aisle, s.rack
GROUP BY s.product_sku, s.lot_number, s.zone, s.aisle, s.bin
HAVING quantity > 0";
},
$warehouses
@@ -1026,7 +1026,7 @@ class ReportManager
stock.lot_number,
stock.zone,
stock.aisle,
stock.rack,
stock.bin,
stock.quantity,
l.expiry_date,
DATEDIFF(l.expiry_date, CURDATE()) AS days_remaining,
@@ -1073,7 +1073,7 @@ class ReportManager
'lot_number' => $row['lot_number'],
'zone' => $row['zone'],
'aisle' => $row['aisle'],
'rack' => $row['rack'],
'bin' => $row['bin'],
'quantity' => (float) $row['quantity'],
'expiry_date' => $row['expiry_date'],
'days_remaining' => $days,
@@ -1085,7 +1085,7 @@ class ReportManager
}
// ─────────────────────────────────────────────────────────────
// REPORT BASIS — Lot / Rack reports
// REPORT BASIS — Lot / Bin reports
// ─────────────────────────────────────────────────────────────
/**
@@ -1097,7 +1097,7 @@ class ReportManager
*
* @param string $product_sku SKU to filter by.
* @param string $lot_number Lot number to filter by.
* @return array Stock rows with date, type, zone/aisle/rack, in/out amounts, warehouse_name.
* @return array Stock rows with date, type, zone/aisle/bin, in/out amounts, warehouse_name.
*/
public function getLotStockLog(string $product_sku, string $lot_number): array
{
@@ -1123,7 +1123,7 @@ class ReportManager
s.type,
s.zone,
s.aisle,
s.rack,
s.bin,
ROUND(COALESCE(s.`in`, 0), 2) AS stock_in,
ROUND(COALESCE(s.`out`, 0), 2) AS stock_out,
s.serial_number,
@@ -1247,21 +1247,21 @@ class ReportManager
}
/**
* Return the action log for a specific rack, with user name.
* Return the action log for a specific bin, with user name.
*
* Used by the rack log dashboard report page.
* Used by the bin log dashboard report page.
* Joins the wms.user table for the acting user's name.
*
* Security fix: the database name is now fetched once via a bound query
* and stored as $db_name (string), then used as a backtick-quoted identifier
* rather than being embedded in the JOIN without escaping.
*
* @param int $rack_id The md_rack.id to fetch logs for (0 returns empty array).
* @param int $bin_id The md_bin.id to fetch logs for (0 returns empty array).
* @return array Log rows with dt, action, product_sku, td_stock_id, login, user_name.
*/
public function getRackLog(int $rack_id): array
public function getBinLog(int $bin_id): array
{
if (!$rack_id) return [];
if (!$bin_id) return [];
$main_db = $this->mainDb;
if ($main_db === '' || !ctype_alnum(str_replace('_', '', $main_db))) {
@@ -1277,30 +1277,30 @@ class ReportManager
rl.td_stock_id,
rl.login,
u.name AS user_name
FROM td_rack_log rl
FROM td_bin_log rl
LEFT JOIN `{$main_db}`.user u
ON u.user_id = rl.user_id
WHERE rl.company_id = :company_id
AND rl.md_rack_id = :rack_id
AND rl.md_bin_id = :bin_id
ORDER BY rl.dt DESC"
);
$sth->execute([
':company_id' => $this->companyId,
':rack_id' => $rack_id,
':bin_id' => $bin_id,
]);
return $sth->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Return all rack slots across all warehouses with occupancy status,
* Return all bin slots across all warehouses with occupancy status,
* warehouse name, and product name.
*
* Used by the rack occupancy dashboard report page to visualise which
* racks are empty vs occupied and which product is in each slot.
* Results are ordered by warehouse → zone → aisle → rack with
* Used by the bin occupancy dashboard report page to visualise which
* bins are empty vs occupied and which product is in each slot.
* Results are ordered by warehouse → zone → aisle → bin with
* numeric-first sorting via CAST.
*
* @return array All md_rack rows joined to warehouse and product with 'status' field.
* @return array All md_bin rows joined to warehouse and product with 'status' field.
*/
public function getRackOccupancy(): array
{
@@ -1309,14 +1309,14 @@ class ReportManager
r.id,
r.zone,
r.aisle,
r.rack,
r.bin,
r.product_sku,
r.td_stock_id,
mw.warehouse_name,
mw.id AS warehouse_id,
p.product_name,
CASE WHEN r.product_sku IS NOT NULL THEN 'occupied' ELSE 'empty' END AS status
FROM md_rack r
FROM md_bin r
INNER JOIN md_warehouse mw
ON mw.company_id = r.company_id
AND mw.id = r.warehouse
@@ -1326,7 +1326,7 @@ class ReportManager
WHERE r.company_id = :company_id
ORDER BY mw.warehouse_name, r.zone,
CAST(r.aisle AS UNSIGNED), r.aisle,
CAST(r.rack AS UNSIGNED), r.rack"
CAST(r.bin AS UNSIGNED), r.bin"
);
$sth->execute([':company_id' => $this->companyId]);
return $sth->fetchAll(PDO::FETCH_ASSOC);
@@ -1510,7 +1510,7 @@ class ReportManager
s.serial_number,
s.zone,
s.aisle,
s.rack,
s.bin,
ROUND(COALESCE(s.`in`, 0), 2) AS stock_in,
ROUND(COALESCE(s.`out`, 0), 2) AS stock_out,
CASE