250 lines
8.3 KiB
PHP
250 lines
8.3 KiB
PHP
<?php
|
|
session_start();
|
|
require '../../../assets/utils/db_auth.php';
|
|
|
|
function stockTableNameFromWarehouseId(int $warehouse_id): string {
|
|
return 'td_stock_' . $warehouse_id;
|
|
}
|
|
|
|
function findProduct(PDO $pdo, int $company_id, string $sku): array|false {
|
|
$sth = $pdo->prepare(
|
|
"SELECT sku, product_name, uom
|
|
FROM md_product
|
|
WHERE company_id = :company_id
|
|
AND sku = :sku
|
|
AND status > 0
|
|
LIMIT 1"
|
|
);
|
|
$sth->execute([':company_id' => $company_id, ':sku' => $sku]);
|
|
return $sth->fetch(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
function activeStockLotExists(PDO $pdo, int $company_id, string $sku, string $lot): bool {
|
|
$warehouses = $pdo->prepare(
|
|
"SELECT id FROM md_warehouse
|
|
WHERE company_id = :company_id AND status = 1"
|
|
);
|
|
$warehouses->execute([':company_id' => $company_id]);
|
|
|
|
foreach ($warehouses->fetchAll(PDO::FETCH_COLUMN) as $warehouse_id) {
|
|
$table = stockTableNameFromWarehouseId((int)$warehouse_id);
|
|
$sth = $pdo->prepare(
|
|
"SELECT ROUND(SUM(COALESCE(`in`, 0)) - SUM(COALESCE(`out`, 0)), 2) AS balance
|
|
FROM `{$table}`
|
|
WHERE company_id = :company_id
|
|
AND product_sku = :product_sku
|
|
AND lot_number = :lot_number
|
|
AND status = 1"
|
|
);
|
|
$sth->execute([
|
|
':company_id' => $company_id,
|
|
':product_sku' => $sku,
|
|
':lot_number' => $lot,
|
|
]);
|
|
if ((float)$sth->fetchColumn() > 0) return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function findLot(PDO $pdo, int $company_id, string $sku, string $lot): array|false {
|
|
$sth = $pdo->prepare(
|
|
"SELECT
|
|
l.product_sku,
|
|
l.lot_number,
|
|
l.expiry_date,
|
|
p.product_name,
|
|
p.uom
|
|
FROM md_lot l
|
|
INNER JOIN md_product p
|
|
ON p.company_id = l.company_id
|
|
AND p.sku = l.product_sku
|
|
WHERE l.company_id = :company_id
|
|
AND l.product_sku = :product_sku
|
|
AND l.lot_number = :lot_number
|
|
AND p.status > 0
|
|
LIMIT 1"
|
|
);
|
|
$sth->execute([
|
|
':company_id' => $company_id,
|
|
':product_sku' => $sku,
|
|
':lot_number' => $lot,
|
|
]);
|
|
$row = $sth->fetch(PDO::FETCH_ASSOC);
|
|
if ($row) return $row;
|
|
|
|
$product = findProduct($pdo, $company_id, $sku);
|
|
if (!$product || !activeStockLotExists($pdo, $company_id, $sku, $lot)) return false;
|
|
|
|
return [
|
|
'product_sku' => $product['sku'],
|
|
'lot_number' => $lot,
|
|
'expiry_date' => null,
|
|
'product_name' => $product['product_name'],
|
|
'uom' => $product['uom'],
|
|
];
|
|
}
|
|
|
|
function listLabels(PDO $pdo, int $company_id, string $sku, string $lot): array {
|
|
$params = [':company_id' => $company_id];
|
|
$where = "WHERE b.company_id = :company_id";
|
|
|
|
if ($sku !== '') {
|
|
$where .= " AND b.product_sku = :product_sku";
|
|
$params[':product_sku'] = $sku;
|
|
}
|
|
|
|
if ($lot !== '') {
|
|
$where .= " AND b.lot_number = :lot_number";
|
|
$params[':lot_number'] = $lot;
|
|
}
|
|
|
|
$sth = $pdo->prepare(
|
|
"SELECT
|
|
b.id,
|
|
b.product_sku,
|
|
b.lot_number,
|
|
b.serial_number,
|
|
b.barcode,
|
|
b.status,
|
|
b.print_count,
|
|
b.last_printed_dt,
|
|
b.created_dt,
|
|
p.product_name
|
|
FROM md_barcode b
|
|
LEFT JOIN md_product p
|
|
ON p.company_id = b.company_id
|
|
AND p.sku = b.product_sku
|
|
{$where}
|
|
AND b.barcode_type = 'sku'
|
|
ORDER BY b.created_dt DESC, b.id DESC"
|
|
);
|
|
$sth->execute($params);
|
|
return $sth->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
$label_action = $data['label_action'] ?? 'read';
|
|
$product_sku = trim($data['product_sku'] ?? '');
|
|
$lot_number = trim($data['lot_number'] ?? '');
|
|
|
|
if (in_array($label_action, ['create', 'print', 'disable', 'enable'], true)) {
|
|
require_role($user_role, ['owner', 'admin', 'staff']);
|
|
}
|
|
|
|
if ($label_action === 'print') {
|
|
$barcode = trim($data['barcode'] ?? '');
|
|
if ($barcode === '') {
|
|
$answer['message'] = 'No barcode provided.';
|
|
http_response_code(400);
|
|
exit(json_encode($answer));
|
|
}
|
|
|
|
$sth = $pdo2->prepare(
|
|
"UPDATE md_barcode
|
|
SET print_count = print_count + 1,
|
|
last_printed_dt = NOW()
|
|
WHERE company_id = :company_id
|
|
AND barcode = :barcode
|
|
AND barcode_type = 'sku'
|
|
AND status = 1"
|
|
);
|
|
$sth->execute([':company_id' => $company_id, ':barcode' => $barcode]);
|
|
|
|
$answer['success'] = 1;
|
|
exit(json_encode($answer));
|
|
}
|
|
|
|
if ($label_action === 'disable') {
|
|
$barcode = trim($data['barcode'] ?? '');
|
|
if ($barcode === '') {
|
|
$answer['message'] = 'No barcode provided.';
|
|
http_response_code(400);
|
|
exit(json_encode($answer));
|
|
}
|
|
|
|
$sth = $pdo2->prepare(
|
|
"UPDATE md_barcode
|
|
SET status = 0
|
|
WHERE company_id = :company_id
|
|
AND barcode = :barcode
|
|
AND barcode_type = 'sku'
|
|
AND status = 1"
|
|
);
|
|
$sth->execute([':company_id' => $company_id, ':barcode' => $barcode]);
|
|
|
|
$answer['success'] = 1;
|
|
exit(json_encode($answer));
|
|
}
|
|
|
|
if ($label_action === 'create') {
|
|
$serial_number = trim($data['serial_number'] ?? '');
|
|
$allow_unlisted = !empty($data['allow_unlisted']);
|
|
|
|
if ($product_sku === '' || $lot_number === '' || $serial_number === '') {
|
|
$answer['message'] = 'SKU, lot no, and serial no are required.';
|
|
http_response_code(400);
|
|
exit(json_encode($answer));
|
|
}
|
|
|
|
$lot = findLot($pdo2, $company_id, $product_sku, $lot_number);
|
|
if (!$lot) {
|
|
if (!$allow_unlisted) {
|
|
$answer['message'] = 'Lot not found.';
|
|
http_response_code(404);
|
|
exit(json_encode($answer));
|
|
}
|
|
|
|
$product = findProduct($pdo2, $company_id, $product_sku);
|
|
if (!$product) {
|
|
$answer['message'] = 'SKU not found.';
|
|
http_response_code(404);
|
|
exit(json_encode($answer));
|
|
}
|
|
|
|
$lot = [
|
|
'product_sku' => $product['sku'],
|
|
'lot_number' => $lot_number,
|
|
'expiry_date' => null,
|
|
'product_name' => $product['product_name'],
|
|
'uom' => $product['uom'],
|
|
];
|
|
}
|
|
|
|
$barcode = "SKU|{$product_sku}|{$lot_number}|{$serial_number}";
|
|
|
|
$sth = $pdo2->prepare(
|
|
"INSERT INTO md_barcode
|
|
(company_id, barcode_type, barcode, product_sku, lot_number, serial_number)
|
|
VALUES
|
|
(:company_id, 'sku', :barcode, :product_sku, :lot_number, :serial_number)
|
|
ON DUPLICATE KEY UPDATE
|
|
barcode_type = VALUES(barcode_type),
|
|
product_sku = VALUES(product_sku),
|
|
lot_number = VALUES(lot_number),
|
|
serial_number = VALUES(serial_number),
|
|
status = 1"
|
|
);
|
|
$sth->execute([
|
|
':company_id' => $company_id,
|
|
':product_sku' => $product_sku,
|
|
':lot_number' => $lot_number,
|
|
':serial_number' => $serial_number,
|
|
':barcode' => $barcode,
|
|
]);
|
|
|
|
$answer['success'] = 1;
|
|
$answer['output'] = [
|
|
'product_sku' => $product_sku,
|
|
'product_name' => $lot['product_name'],
|
|
'lot_number' => $lot_number,
|
|
'serial_number' => $serial_number,
|
|
'barcode' => $barcode,
|
|
];
|
|
exit(json_encode($answer));
|
|
}
|
|
|
|
$answer['success'] = 1;
|
|
$answer['output'] = listLabels($pdo2, $company_id, $product_sku, $lot_number);
|
|
exit(json_encode($answer));
|
|
?>
|