Classe methods: remove reducdancy
This commit is contained in:
@@ -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}`
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user