[OOP] contact,inventory,ics,dashboard

This commit is contained in:
Thanakorn S
2026-04-28 15:44:57 +07:00
parent 3d3b497c08
commit 2061624641
49 changed files with 1946 additions and 2146 deletions
+9 -129
View File
@@ -1,145 +1,25 @@
<?php
<?php
session_start();
require '../../../assets/utils/db_auth.php';
require '../../../assets/utils/classes/StockManager.php';
require '../../../assets/utils/classes/WarehouseManager.php';
try {
dbTransaction($pdo2, function($pdo) use ($data, $company_id, $logging, $uuid) {
$id = (int)$data['id'];
$warehouse_id = (int)$data["warehouse"];
$whMgmt = new WarehouseManager($pdo, $company_id);
$warehouse = $whMgmt->getStockContext($warehouse_id, $id);
$row = $warehouse['row'] ?? [];
$table = $warehouse['table'];
// Append this edit/create event to td_stock_<wh>.log (stock record history)
$table_log = json_decode($row['log'] ?? '[]', true);
$table_log[] = $logging;
if ($id > 0) {
// UPDATE existing stock_out record
$sql = "UPDATE `$table` SET
`contact_id` = :contact_id,
`description` = :description,
`log` = :log
WHERE id = :id AND company_id = :company_id";
$sth = $pdo->prepare($sql);
$sth->execute([
":id" => $id,
":company_id" => $company_id,
":contact_id" => (int)$data["contact_id"],
":description" => $data["description"],
":log" => json_encode($table_log),
]);
} else {
// Look up the source stock record via the rack.
// Under 1:1, the rack points to exactly one td_stock_<wh> row.
$source_stock = $whMgmt->getRackStock(
$warehouse_id,
$data["zone"],
$data["aisle"],
$data["rack"]
);
if (!$source_stock) {
throw new Exception(
"Rack {$data['zone']}-{$data['aisle']}-{$data['rack']} is empty — nothing to take out."
);
}
// Defensive checks — UI cascade should already prevent mismatches
if ($source_stock['product_sku'] !== $data["product_sku"]) {
throw new Exception(
"Rack holds {$source_stock['product_sku']}, not {$data['product_sku']}."
);
}
// If user selected a specific lot, verify it matches the rack's stock
if (!empty($data["lot_number"]) && $source_stock['lot_number'] !== $data["lot_number"]) {
throw new Exception(
"Rack holds lot '{$source_stock['lot_number']}', not '{$data['lot_number']}'."
);
}
// If user selected a specific serial, verify it matches the rack's stock
if (!empty($data["serial_number"]) && $source_stock['serial_number'] !== $data["serial_number"]) {
throw new Exception(
"Rack holds serial '{$source_stock['serial_number']}', not '{$data['serial_number']}'."
);
}
// Quantity comes from the source stock_in row, NOT user input.
// Under 1:1, taking from this rack = taking the full batch.
$quantity = (int) $source_stock['in'];
$ref_id = (int) $source_stock['id'];
$lot_number = $source_stock['lot_number'] ?? null;
$serial_number = $source_stock['serial_number'] ?? null;
// INSERT new stock_out record.
// lot_number and serial_number carried from source stock_in row.
// ref_id links this stock_out row back to the stock_in batch it consumed.
$sql = "INSERT INTO `$table`
(uuid, company_id, `date`, product_sku, `out`, zone, aisle, rack,
contact_id, `description`, `log`, `type`, ref_id, lot_number, serial_number)
VALUES
(:uuid, :company_id, :date, :product_sku, :quantity, :zone, :aisle, :rack,
:contact_id, :description, :log, 'out', :ref_id, :lot_number, :serial_number)";
$sth = $pdo->prepare($sql);
$sth->execute([
":uuid" => $uuid,
":company_id" => $company_id,
":date" => date('Y-m-d H:i:s'),
":product_sku" => $data["product_sku"],
":quantity" => $quantity,
":zone" => $data["zone"],
":aisle" => $data["aisle"],
":rack" => $data["rack"],
":contact_id" => (int)$data["contact_id"],
":description" => $data["description"],
":log" => json_encode($table_log),
":ref_id" => $ref_id,
":lot_number" => $lot_number,
":serial_number" => $serial_number,
]);
// Release the rack — stock is now gone from this location.
$whMgmt->releaseRack(
$warehouse_id,
$data["zone"], $data["aisle"], $data["rack"]
);
// Balance: total_out increases by delta.
// INSERT: $row['out'] = 0 → delta = full quantity
// UPDATE: $row['out'] = old → delta = new - old
$whMgmt->adjustBalance(
'out',
$warehouse_id,
$data["product_sku"],
$row['out'] ?? 0,
$quantity
);
}
$stock = new StockManager($pdo, $company_id);
$stock->saveStockOut($data, $logging, $uuid);
});
$answer["success"] = 1;
$answer['success'] = 1;
} catch (PDOException $e) {
$answer["success"] = 0;
$answer["message"] = "Database error, please try again";
$answer['success'] = 0;
$answer['message'] = 'Database error, please try again';
http_response_code(500);
} catch (Exception $e) {
$answer["success"] = 0;
$answer["message"] = $e->getMessage();
$answer['success'] = 0;
$answer['message'] = $e->getMessage();
http_response_code(400);
}