173 lines
7.9 KiB
PHP
173 lines
7.9 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../db/config.php';
|
|
header('Content-Type: application/json');
|
|
|
|
$action = $_GET['action'] ?? '';
|
|
$pdo = db();
|
|
|
|
try {
|
|
switch ($action) {
|
|
case 'get_stock':
|
|
// List all drugs with total stock quantity
|
|
$sql = "SELECT d.id, d.name_en, d.name_ar, d.min_stock_level, d.reorder_level, d.unit,
|
|
COALESCE(SUM(b.quantity), 0) as total_stock
|
|
FROM drugs d
|
|
LEFT JOIN pharmacy_batches b ON d.id = b.drug_id AND b.quantity > 0 AND b.expiry_date >= CURDATE()
|
|
GROUP BY d.id
|
|
ORDER BY d.name_en ASC";
|
|
$stmt = $pdo->query($sql);
|
|
echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC));
|
|
break;
|
|
|
|
case 'get_batches':
|
|
$drug_id = $_GET['drug_id'] ?? 0;
|
|
if (!$drug_id) throw new Exception("Drug ID required");
|
|
|
|
$sql = "SELECT b.*, s.name_en as supplier_name
|
|
FROM pharmacy_batches b
|
|
LEFT JOIN suppliers s ON b.supplier_id = s.id
|
|
WHERE b.drug_id = ? AND b.quantity > 0
|
|
ORDER BY b.expiry_date ASC";
|
|
$stmt = $pdo->prepare($sql);
|
|
$stmt->execute([$drug_id]);
|
|
echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC));
|
|
break;
|
|
|
|
case 'add_stock':
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') throw new Exception("Invalid method");
|
|
|
|
$drug_id = $_POST['drug_id'] ?? 0;
|
|
$batch_number = $_POST['batch_number'] ?? '';
|
|
$expiry_date = $_POST['expiry_date'] ?? '';
|
|
$quantity = $_POST['quantity'] ?? 0;
|
|
$cost_price = $_POST['cost_price'] ?? 0;
|
|
$sale_price = $_POST['sale_price'] ?? 0;
|
|
$supplier_id = !empty($_POST['supplier_id']) ? $_POST['supplier_id'] : null;
|
|
|
|
if (!$drug_id || !$batch_number || !$expiry_date || !$quantity) {
|
|
throw new Exception("Missing required fields");
|
|
}
|
|
|
|
$stmt = $pdo->prepare("INSERT INTO pharmacy_batches
|
|
(drug_id, batch_number, expiry_date, quantity, cost_price, sale_price, supplier_id, received_date)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, CURDATE())");
|
|
$stmt->execute([$drug_id, $batch_number, $expiry_date, $quantity, $cost_price, $sale_price, $supplier_id]);
|
|
|
|
echo json_encode(['success' => true, 'message' => 'Stock added successfully']);
|
|
break;
|
|
|
|
case 'search_drugs':
|
|
$q = $_GET['q'] ?? '';
|
|
$sql = "SELECT d.id, d.name_en, d.name_ar, d.sku, d.price as default_price,
|
|
(SELECT sale_price FROM pharmacy_batches pb WHERE pb.drug_id = d.id AND pb.quantity > 0 AND pb.expiry_date >= CURDATE() ORDER BY pb.expiry_date ASC LIMIT 1) as batch_price,
|
|
COALESCE(SUM(b.quantity), 0) as stock
|
|
FROM drugs d
|
|
LEFT JOIN pharmacy_batches b ON d.id = b.drug_id AND b.quantity > 0 AND b.expiry_date >= CURDATE()
|
|
WHERE (d.name_en LIKE ? OR d.name_ar LIKE ? OR d.sku LIKE ?)
|
|
GROUP BY d.id
|
|
LIMIT 20";
|
|
$stmt = $pdo->prepare($sql);
|
|
$term = "%$q%";
|
|
$stmt->execute([$term, $term, $term]);
|
|
echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC));
|
|
break;
|
|
|
|
case 'create_sale':
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') throw new Exception("Invalid method");
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
|
|
if (empty($input['items'])) throw new Exception("No items in sale");
|
|
|
|
$pdo->beginTransaction();
|
|
|
|
try {
|
|
// Create Sale Record
|
|
$stmt = $pdo->prepare("INSERT INTO pharmacy_sales (patient_id, visit_id, total_amount, payment_method, status) VALUES (?, ?, ?, ?, 'completed')");
|
|
$stmt->execute([
|
|
$input['patient_id'] ?? null,
|
|
$input['visit_id'] ?? null,
|
|
$input['total_amount'] ?? 0,
|
|
$input['payment_method'] ?? 'cash'
|
|
]);
|
|
$sale_id = $pdo->lastInsertId();
|
|
|
|
// Process Items
|
|
foreach ($input['items'] as $item) {
|
|
$drug_id = $item['drug_id'];
|
|
$qty_needed = $item['quantity'];
|
|
$unit_price = $item['price']; // Or fetch from batch? Use provided price for now.
|
|
|
|
// Fetch available batches (FIFO)
|
|
$batch_stmt = $pdo->prepare("SELECT id, quantity FROM pharmacy_batches WHERE drug_id = ? AND quantity > 0 ORDER BY expiry_date ASC FOR UPDATE");
|
|
$batch_stmt->execute([$drug_id]);
|
|
$batches = $batch_stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
$qty_remaining = $qty_needed;
|
|
|
|
foreach ($batches as $batch) {
|
|
if ($qty_remaining <= 0) break;
|
|
|
|
$take = min($batch['quantity'], $qty_remaining);
|
|
|
|
// Deduct from batch
|
|
$update = $pdo->prepare("UPDATE pharmacy_batches SET quantity = quantity - ? WHERE id = ?");
|
|
$update->execute([$take, $batch['id']]);
|
|
|
|
// Add to sale items
|
|
$item_stmt = $pdo->prepare("INSERT INTO pharmacy_sale_items (sale_id, drug_id, batch_id, quantity, unit_price, total_price) VALUES (?, ?, ?, ?, ?, ?)");
|
|
$item_stmt->execute([$sale_id, $drug_id, $batch['id'], $take, $unit_price, $take * $unit_price]);
|
|
|
|
$qty_remaining -= $take;
|
|
}
|
|
|
|
if ($qty_remaining > 0) {
|
|
throw new Exception("Insufficient stock for drug ID: $drug_id");
|
|
}
|
|
}
|
|
|
|
$pdo->commit();
|
|
echo json_encode(['success' => true, 'sale_id' => $sale_id]);
|
|
|
|
} catch (Exception $e) {
|
|
$pdo->rollBack();
|
|
throw $e;
|
|
}
|
|
break;
|
|
|
|
case 'get_sales':
|
|
// List recent sales
|
|
$sql = "SELECT s.*, p.name as patient_name
|
|
FROM pharmacy_sales s
|
|
LEFT JOIN patients p ON s.patient_id = p.id
|
|
ORDER BY s.created_at DESC LIMIT 50";
|
|
$stmt = $pdo->query($sql);
|
|
echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC));
|
|
break;
|
|
|
|
case 'get_sale_details':
|
|
$sale_id = $_GET['sale_id'] ?? 0;
|
|
if (!$sale_id) throw new Exception("Sale ID required");
|
|
|
|
$stmt = $pdo->prepare("SELECT s.*, p.name as patient_name FROM pharmacy_sales s LEFT JOIN patients p ON s.patient_id = p.id WHERE s.id = ?");
|
|
$stmt->execute([$sale_id]);
|
|
$sale = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if (!$sale) throw new Exception("Sale not found");
|
|
|
|
$items_stmt = $pdo->prepare("SELECT i.*, d.name_en as drug_name
|
|
FROM pharmacy_sale_items i
|
|
JOIN drugs d ON i.drug_id = d.id
|
|
WHERE i.sale_id = ?");
|
|
$items_stmt->execute([$sale_id]);
|
|
$sale['items'] = $items_stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
echo json_encode($sale);
|
|
break;
|
|
|
|
default:
|
|
throw new Exception("Invalid action");
|
|
}
|
|
} catch (Exception $e) {
|
|
http_response_code(400);
|
|
echo json_encode(['error' => $e->getMessage()]);
|
|
} |