Classe methods: remove reducdancy

This commit is contained in:
Thanakorn S
2026-05-29 08:56:58 +07:00
parent 356d308907
commit 7b294f70da
9 changed files with 112 additions and 93 deletions
+2 -2
View File
@@ -84,7 +84,7 @@ class BarcodeManager {
$warehouses->execute([':company_id' => $this->company_id]);
foreach ($warehouses->fetchAll(PDO::FETCH_COLUMN) as $warehouse_id) {
$table = $this->stockTableName((int)$warehouse_id);
$table = 'td_stock_' . (int)$warehouse_id;
$sth = $this->pdo->prepare(
"SELECT lot_number
FROM `{$table}`
@@ -169,7 +169,7 @@ class BarcodeManager {
$warehouses->execute([':company_id' => $this->company_id]);
foreach ($warehouses->fetchAll(PDO::FETCH_COLUMN) as $warehouse_id) {
$table = $this->stockTableName((int)$warehouse_id);
$table = 'td_stock_' . (int)$warehouse_id;
$sth = $this->pdo->prepare(
"SELECT ROUND(SUM(COALESCE(`in`, 0)) - SUM(COALESCE(`out`, 0)), 2) AS balance
FROM `{$table}`
+4 -7
View File
@@ -44,14 +44,11 @@ class ContactManager {
private function hasActiveStock(int $contact_id): bool {
$sth = $this->pdo->prepare(
"SELECT t.table_name
FROM md_warehouse w
JOIN information_schema.tables t
ON t.table_schema = DATABASE()
AND t.table_name = CONCAT('td_stock_', w.id)
WHERE w.company_id = :company_id"
"SELECT table_name FROM information_schema.tables
WHERE table_schema = DATABASE()
AND table_name LIKE 'td_stock_%'"
);
$sth->execute([':company_id' => $this->company_id]);
$sth->execute();
$tables = $sth->fetchAll(PDO::FETCH_COLUMN);
foreach ($tables as $table) {
+24 -19
View File
@@ -86,20 +86,6 @@ class OrderManager {
return 'td_stock_' . $warehouse_id;
}
private function getStockTables(): array
{
$sth = $this->pdo->prepare(
"SELECT t.table_name
FROM md_warehouse w
JOIN information_schema.tables t
ON t.table_schema = DATABASE()
AND t.table_name = CONCAT('td_stock_', w.id)
WHERE w.company_id = :company_id"
);
$sth->execute([':company_id' => $this->company_id]);
return $sth->fetchAll(PDO::FETCH_COLUMN);
}
/**
* FIFO bin pick — find the oldest approved stock-in row for a SKU
* in a given warehouse that is still bin-occupied.
@@ -198,7 +184,7 @@ class OrderManager {
$stock_out_id = (int)($item['stock_out_id'] ?? 0);
if ($warehouse_id <= 0 || $stock_out_id <= 0) continue;
$table = $this->stockTableNameFromWarehouseId($warehouse_id);
$table = 'td_stock_' . $warehouse_id;
$sth = $this->pdo->prepare(
"SELECT status FROM `{$table}`
WHERE company_id = :company_id
@@ -379,7 +365,7 @@ class OrderManager {
$stock_out_id = (int)($item['stock_out_id'] ?? 0);
if ($stock_out_warehouse_id > 0 && $stock_out_id > 0) {
$table = $this->stockTableNameFromWarehouseId($stock_out_warehouse_id);
$table = 'td_stock_' . $stock_out_warehouse_id;
$sth = $this->pdo->prepare(
"SELECT id, status, zone, aisle, bin, lot_number, serial_number
FROM `{$table}`
@@ -716,6 +702,22 @@ class OrderManager {
throw new Exception(implode("\n", $preflight_errors));
}
// Validate all warehouse IDs in one query before entering the item loop.
$itemWarehouseIds = array_values(array_unique(array_filter(
array_map(fn($item) => (int)($item['warehouse_id'] ?? 0), $items),
fn($id) => $id > 0
)));
if (!empty($itemWarehouseIds)) {
$placeholders = implode(',', array_fill(0, count($itemWarehouseIds), '?'));
$sth = $this->pdo->prepare(
"SELECT id FROM md_warehouse WHERE company_id = ? AND id IN ($placeholders)"
);
$sth->execute([$this->company_id, ...$itemWarehouseIds]);
$validWarehouseIds = array_flip($sth->fetchAll(PDO::FETCH_COLUMN));
} else {
$validWarehouseIds = [];
}
foreach ($items as $i => &$item) {
$warehouse_id = (int)($item['warehouse_id'] ?? 0);
@@ -725,7 +727,10 @@ class OrderManager {
$bin_stock = $this->pickFifoRack($warehouse_id, $product_sku);
$available_qty = (float)($bin_stock['available_qty'] ?? $bin_stock['in'] ?? 0);
$table = $this->stockTableNameFromWarehouseId($warehouse_id);
if (!isset($validWarehouseIds[$warehouse_id])) {
throw new Exception("Warehouse ID {$warehouse_id} not found.");
}
$table = 'td_stock_' . $warehouse_id;
$item_uuid = $uuid . '_' . $i;
$item_log = [array_merge($logging, ['action' => 'confirm_item'])];
@@ -888,8 +893,8 @@ class OrderManager {
}
// ── Reverse approved stock-out side effects, then soft-delete rows ─
$tables = $this->getStockTables();
$whMgmt = new WarehouseManager($this->pdo, $this->company_id);
$tables = $whMgmt->getStockTables();
foreach ($tables as $table) {
if (!preg_match('/^td_stock_(\d+)$/', (string)$table, $matches)) {
@@ -1034,7 +1039,7 @@ class OrderManager {
}
// Block if any approved stock-out rows exist; user must reverse via ICS first
$tables = $this->getStockTables();
$tables = (new WarehouseManager($this->pdo, $this->company_id))->getStockTables();
foreach ($tables as $table) {
$chk = $this->pdo->prepare(
+4 -7
View File
@@ -45,14 +45,11 @@ class ProductManager {
private function findActiveStock(string $sku): ?string {
$sth = $this->pdo->prepare(
"SELECT t.table_name
FROM md_warehouse w
JOIN information_schema.tables t
ON t.table_schema = DATABASE()
AND t.table_name = CONCAT('td_stock_', w.id)
WHERE w.company_id = :company_id"
"SELECT table_name FROM information_schema.tables
WHERE table_schema = DATABASE()
AND table_name LIKE 'td_stock_%'"
);
$sth->execute([':company_id' => $this->company_id]);
$sth->execute();
$tables = $sth->fetchAll(PDO::FETCH_COLUMN);
foreach ($tables as $table) {
@@ -1,5 +1,6 @@
<?php
require_once __DIR__ . '/DocumentNumberManager.php';
require_once __DIR__ . '/WarehouseManager.php';
require_once __DIR__ . '/../classes_ac/PostingWindowGuard.php';
/**
@@ -97,7 +98,7 @@ class PurchaseOrderManager {
}
if (!$has_any_stock_in) return 0;
$tables = $this->getStockTables();
$tables = (new WarehouseManager($this->pdo, $this->company_id))->getStockTables();
$total = 0;
$pending = 0;
@@ -149,20 +150,6 @@ class PurchaseOrderManager {
return 'td_stock_' . $warehouse_id;
}
private function getStockTables(): array
{
$sth = $this->pdo->prepare(
"SELECT t.table_name
FROM md_warehouse w
JOIN information_schema.tables t
ON t.table_schema = DATABASE()
AND t.table_name = CONCAT('td_stock_', w.id)
WHERE w.company_id = :company_id"
);
$sth->execute([':company_id' => $this->company_id]);
return $sth->fetchAll(PDO::FETCH_COLUMN);
}
private function syncPoItems(int $po_id, array $items): void
{
$this->pdo->prepare(
@@ -563,6 +550,22 @@ class PurchaseOrderManager {
$stock = new StockManager($this->pdo, $this->company_id);
$whMgmt = new WarehouseManager($this->pdo, $this->company_id);
// Validate all warehouse IDs in one query before entering the item loop.
$recvWarehouseIds = array_values(array_unique(array_filter(
array_map(fn($recv) => (int)($recv['warehouse_id'] ?? $po['warehouse_id']), $receive_items),
fn($id) => $id > 0
)));
if (!empty($recvWarehouseIds)) {
$placeholders = implode(',', array_fill(0, count($recvWarehouseIds), '?'));
$sth = $this->pdo->prepare(
"SELECT id FROM md_warehouse WHERE company_id = ? AND id IN ($placeholders)"
);
$sth->execute([$this->company_id, ...$recvWarehouseIds]);
$validWarehouseIds = array_flip($sth->fetchAll(PDO::FETCH_COLUMN));
} else {
$validWarehouseIds = [];
}
foreach ($receive_items as $j => $recv) {
$item_id = (int)($recv['item_id'] ?? -1);
$product_sku = $recv['product_sku'] ?? '';
@@ -632,7 +635,10 @@ class PurchaseOrderManager {
// saveStockIn() does not write source/source_id — stamp them here.
// This links the stock-in row back to this PO for cancellation guards
// and makes it appear under the "PO" source tab on the Stock In list.
$table = $this->stockTableNameFromWarehouseId($warehouse_id);
if (!isset($validWarehouseIds[$warehouse_id])) {
throw new Exception("Warehouse ID {$warehouse_id} not found.");
}
$table = 'td_stock_' . $warehouse_id;
$this->pdo->prepare(
"UPDATE `{$table}` SET source = 'po', source_id = :po_id
WHERE id = :id AND company_id = :company_id"
@@ -746,7 +752,8 @@ class PurchaseOrderManager {
if ($status === -1) throw new Exception("PO is already cancelled.");
// Guard: block if any approved stock-in rows exist for this PO
$tables = $this->getStockTables();
$whMgmt = new WarehouseManager($this->pdo, $this->company_id);
$tables = $whMgmt->getStockTables();
foreach ($tables as $table) {
$sth = $this->pdo->prepare(
@@ -765,8 +772,6 @@ class PurchaseOrderManager {
}
}
$whMgmt = new WarehouseManager($this->pdo, $this->company_id);
// Soft-delete draft stock-in rows and release their bin reservations.
foreach ($tables as $table) {
if (!preg_match('/^td_stock_(\d+)$/', $table, $m)) {
@@ -887,7 +892,8 @@ class PurchaseOrderManager {
throw new Exception('Cannot delete — this PO has linked supplier returns. Delete or cancel the returns first.');
}
$tables = $this->getStockTables();
$whMgmt = new WarehouseManager($this->pdo, $this->company_id);
$tables = $whMgmt->getStockTables();
foreach ($tables as $table) {
$sth5 = $this->pdo->prepare(
@@ -901,7 +907,6 @@ class PurchaseOrderManager {
}
// Release bins from draft stock-in rows and negate them
$whMgmt = new WarehouseManager($this->pdo, $this->company_id);
foreach ($tables as $table) {
if (!preg_match('/^td_stock_(\d+)$/', (string)$table, $matches)) continue;
$warehouse_id = (int)$matches[1];
+6 -17
View File
@@ -1,6 +1,7 @@
<?php
require_once __DIR__ . '/DocumentNumberManager.php';
require_once __DIR__ . '/../classes_ac/PostingWindowGuard.php';
require_once __DIR__ . '/WarehouseManager.php';
/**
* ReturnManager
@@ -88,14 +89,11 @@ class ReturnManager {
private function deriveReceiptStatus(array $ret): int
{
$sth = $this->pdo->prepare(
"SELECT t.table_name
FROM md_warehouse w
JOIN information_schema.tables t
ON t.table_schema = DATABASE()
AND t.table_name = CONCAT('td_stock_', w.id)
WHERE w.company_id = :company_id"
"SELECT table_name FROM information_schema.tables
WHERE table_schema = DATABASE()
AND table_name LIKE 'td_stock_%'"
);
$sth->execute([':company_id' => $this->company_id]);
$sth->execute();
$tables = $sth->fetchAll(PDO::FETCH_COLUMN);
foreach ($tables as $table) {
@@ -749,16 +747,7 @@ class ReturnManager {
}
// Block if any approved stock-in rows exist; user must reverse via ICS first
$sth = $this->pdo->prepare(
"SELECT t.table_name
FROM md_warehouse w
JOIN information_schema.tables t
ON t.table_schema = DATABASE()
AND t.table_name = CONCAT('td_stock_', w.id)
WHERE w.company_id = :company_id"
);
$sth->execute([':company_id' => $this->company_id]);
$tables = $sth->fetchAll(PDO::FETCH_COLUMN);
$tables = (new WarehouseManager($this->pdo, $this->company_id))->getStockTables();
foreach ($tables as $table) {
$chk = $this->pdo->prepare(
@@ -0,0 +1,26 @@
<?php
/**
* Provides getStockTables() — discovers td_stock_* tables scoped to this
* company's active and historical warehouses via an information_schema JOIN.
*
* Requires the using class to expose:
* $this->pdo PDO
* $this->company_id int
*/
trait StockTablesTrait
{
private function getStockTables(): array
{
$sth = $this->pdo->prepare(
"SELECT t.table_name
FROM md_warehouse w
JOIN information_schema.tables t
ON t.table_schema = DATABASE()
AND t.table_name = CONCAT('td_stock_', w.id)
WHERE w.company_id = :company_id"
);
$sth->execute([':company_id' => $this->company_id]);
return $sth->fetchAll(PDO::FETCH_COLUMN);
}
}
@@ -1,6 +1,8 @@
<?php
require_once __DIR__ . '/DocumentNumberManager.php';
require_once __DIR__ . '/StockTablesTrait.php';
require_once __DIR__ . '/../classes_ac/PostingWindowGuard.php';
require_once __DIR__ . '/WarehouseManager.php';
/**
* SupplierReturnManager
@@ -27,6 +29,8 @@ require_once __DIR__ . '/../classes_ac/PostingWindowGuard.php';
*/
class SupplierReturnManager {
use StockTablesTrait;
private PDO $pdo;
private int $company_id;
@@ -69,16 +73,7 @@ class SupplierReturnManager {
*/
private function deriveFulfillmentStatus(array $ret): int
{
$sth = $this->pdo->prepare(
"SELECT t.table_name
FROM md_warehouse w
JOIN information_schema.tables t
ON t.table_schema = DATABASE()
AND t.table_name = CONCAT('td_stock_', w.id)
WHERE w.company_id = :company_id"
);
$sth->execute([':company_id' => $this->company_id]);
$tables = $sth->fetchAll(PDO::FETCH_COLUMN);
$tables = $this->getStockTables();
$has_stock_out = false;
$has_draft = false;
@@ -650,16 +645,7 @@ class SupplierReturnManager {
}
// Block if any approved stock-out rows exist; user must reverse via ICS first
$sth = $this->pdo->prepare(
"SELECT t.table_name
FROM md_warehouse w
JOIN information_schema.tables t
ON t.table_schema = DATABASE()
AND t.table_name = CONCAT('td_stock_', w.id)
WHERE w.company_id = :company_id"
);
$sth->execute([':company_id' => $this->company_id]);
$tables = $sth->fetchAll(PDO::FETCH_COLUMN);
$tables = $this->getStockTables();
foreach ($tables as $table) {
$chk = $this->pdo->prepare(
@@ -52,6 +52,20 @@ class WarehouseManager {
return 'td_stock_' . $warehouse_id;
}
public function getStockTables(): array
{
$sth = $this->pdo->prepare(
"SELECT t.table_name
FROM md_warehouse w
JOIN information_schema.tables t
ON t.table_schema = DATABASE()
AND t.table_name = CONCAT('td_stock_', w.id)
WHERE w.company_id = :company_id"
);
$sth->execute([':company_id' => $this->company_id]);
return $sth->fetchAll(PDO::FETCH_COLUMN);
}
public function assertStockMovementWindow(?string $date, string $context = 'Stock movement'): void
{
global $pdo1;