38960-vm/api/pharmacy_lpo.php
2026-03-21 12:43:58 +00:00

282 lines
12 KiB
PHP

<?php
require_once __DIR__ . '/../db/config.php';
header('Content-Type: application/json');
$action = $_GET['action'] ?? '';
try {
$pdo = db();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if ($action === 'create_lpo') {
$data = json_decode(file_get_contents('php://input'), true);
if (empty($data['supplier_id']) || empty($data['items'])) {
throw new Exception("Supplier and items are required.");
}
$pdo->beginTransaction();
$stmt = $pdo->prepare("INSERT INTO pharmacy_lpos (supplier_id, lpo_date, status, total_amount, notes) VALUES (?, ?, 'Draft', ?, ?)");
$stmt->execute([
$data['supplier_id'],
$data['lpo_date'] ?? date('Y-m-d'),
$data['total_amount'] ?? 0,
$data['notes'] ?? ''
]);
$lpoId = $pdo->lastInsertId();
$stmtItem = $pdo->prepare("INSERT INTO pharmacy_lpo_items (lpo_id, drug_id, quantity, cost_price, total_cost, batch_number, expiry_date) VALUES (?, ?, ?, ?, ?, ?, ?)");
foreach ($data['items'] as $item) {
$stmtItem->execute([
$lpoId,
$item['drug_id'],
$item['quantity'],
$item['cost_price'],
$item['total_cost'],
!empty($item['batch_number']) ? $item['batch_number'] : null,
!empty($item['expiry_date']) ? $item['expiry_date'] : null
]);
}
$pdo->commit();
echo json_encode(['success' => true, 'message' => 'Purchase created successfully']);
} elseif ($action === 'update_status') {
$data = json_decode(file_get_contents('php://input'), true);
if (empty($data['id']) || empty($data['status'])) {
throw new Exception("ID and Status are required");
}
$pdo->beginTransaction();
// Check if items update is requested (specifically for Received status or corrections)
if (!empty($data['items']) && is_array($data['items'])) {
$updateItemStmt = $pdo->prepare("UPDATE pharmacy_lpo_items SET batch_number = ?, expiry_date = ? WHERE id = ?");
foreach ($data['items'] as $item) {
if (!empty($item['id'])) {
$updateItemStmt->execute([
!empty($item['batch_number']) ? $item['batch_number'] : null,
!empty($item['expiry_date']) ? $item['expiry_date'] : null,
$item['id']
]);
}
}
}
// If status is being changed to Received, we must update stock
if ($data['status'] === 'Received') {
// Fetch LPO items (re-fetch to get updated values)
$stmtItems = $pdo->prepare("SELECT * FROM pharmacy_lpo_items WHERE lpo_id = ?");
$stmtItems->execute([$data['id']]);
$items = $stmtItems->fetchAll(PDO::FETCH_ASSOC);
// Fetch LPO details for supplier
$stmtLPO = $pdo->prepare("SELECT supplier_id FROM pharmacy_lpos WHERE id = ?");
$stmtLPO->execute([$data['id']]);
$lpo = $stmtLPO->fetch(PDO::FETCH_ASSOC);
$batchStmt = $pdo->prepare("INSERT INTO pharmacy_batches (drug_id, batch_number, expiry_date, quantity, cost_price, sale_price, supplier_id, received_date) VALUES (?, ?, ?, ?, ?, ?, ?, CURDATE())");
// We need sale price for the batch. Ideally, LPO should have it or we fetch current from drugs table.
$drugPriceStmt = $pdo->prepare("SELECT price FROM drugs WHERE id = ?");
foreach ($items as $item) {
if (empty($item['batch_number']) || empty($item['expiry_date'])) {
// If still missing (should be caught by UI), generate defaults
$item['batch_number'] = $item['batch_number'] ?? 'BATCH-' . date('Ymd') . '-' . $item['id'];
$item['expiry_date'] = $item['expiry_date'] ?? date('Y-m-d', strtotime('+1 year'));
}
$drugPriceStmt->execute([$item['drug_id']]);
$drug = $drugPriceStmt->fetch(PDO::FETCH_ASSOC);
$salePrice = $drug['price'] ?? ($item['cost_price'] * 1.5); // Fallback margin
$batchStmt->execute([
$item['drug_id'],
$item['batch_number'],
$item['expiry_date'],
$item['quantity'],
$item['cost_price'],
$salePrice,
$lpo['supplier_id']
]);
}
}
$stmt = $pdo->prepare("UPDATE pharmacy_lpos SET status = ? WHERE id = ?");
$stmt->execute([$data['status'], $data['id']]);
$pdo->commit();
echo json_encode(['success' => true]);
} elseif ($action === 'create_return') {
$data = json_decode(file_get_contents('php://input'), true);
if (empty($data['supplier_id']) || empty($data['items'])) {
throw new Exception("Supplier and items are required.");
}
$pdo->beginTransaction();
$stmt = $pdo->prepare("INSERT INTO pharmacy_purchase_returns (supplier_id, return_date, total_amount, reason) VALUES (?, ?, ?, ?)");
$stmt->execute([
$data['supplier_id'],
$data['return_date'] ?? date('Y-m-d'),
$data['total_amount'] ?? 0,
$data['reason'] ?? ''
]);
$returnId = $pdo->lastInsertId();
$stmtItem = $pdo->prepare("INSERT INTO pharmacy_purchase_return_items (return_id, drug_id, batch_id, quantity, unit_price, total_price) VALUES (?, ?, ?, ?, ?, ?)");
$updateBatch = $pdo->prepare("UPDATE pharmacy_batches SET quantity = quantity - ? WHERE id = ?");
foreach ($data['items'] as $item) {
// Check stock first
$checkBatch = $pdo->prepare("SELECT quantity FROM pharmacy_batches WHERE id = ?");
$checkBatch->execute([$item['batch_id']]);
$currentStock = $checkBatch->fetchColumn();
if ($currentStock < $item['quantity']) {
throw new Exception("Insufficient stock in batch for drug ID " . $item['drug_id']);
}
$stmtItem->execute([
$returnId,
$item['drug_id'],
$item['batch_id'],
$item['quantity'],
$item['unit_price'],
$item['total_price']
]);
// Deduct stock
$updateBatch->execute([$item['quantity'], $item['batch_id']]);
}
$pdo->commit();
echo json_encode(['success' => true, 'message' => 'Return created successfully']);
}
} elseif ($_SERVER['REQUEST_METHOD'] === 'GET') {
if ($action === 'get_lpos') {
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 20;
$offset = ($page - 1) * $limit;
// Count total
$countStmt = $pdo->query("SELECT COUNT(*) FROM pharmacy_lpos");
$total = $countStmt->fetchColumn();
$stmt = $pdo->prepare("
SELECT l.*, s.name_en as supplier_name
FROM pharmacy_lpos l
LEFT JOIN suppliers s ON l.supplier_id = s.id
ORDER BY l.created_at DESC
LIMIT :limit OFFSET :offset
");
$stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
$stmt->execute();
echo json_encode([
'data' => $stmt->fetchAll(PDO::FETCH_ASSOC),
'total' => $total,
'page' => $page,
'limit' => $limit,
'pages' => ceil($total / $limit)
]);
} elseif ($action === 'get_lpo_details') {
$id = $_GET['id'] ?? 0;
$stmt = $pdo->prepare("
SELECT i.*, d.name_en as drug_name, d.sku
FROM pharmacy_lpo_items i
LEFT JOIN drugs d ON i.drug_id = d.id
WHERE i.lpo_id = ?
");
$stmt->execute([$id]);
echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC));
} elseif ($action === 'get_suppliers') {
$stmt = $pdo->query("SELECT id, name_en, name_ar FROM suppliers ORDER BY name_en ASC");
echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC));
} elseif ($action === 'get_drugs') {
$stmt = $pdo->query("SELECT id, name_en, name_ar, sku, price FROM drugs ORDER BY name_en ASC");
echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC));
} elseif ($action === 'get_returns') {
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 20;
$offset = ($page - 1) * $limit;
$countStmt = $pdo->query("SELECT COUNT(*) FROM pharmacy_purchase_returns");
$total = $countStmt->fetchColumn();
$stmt = $pdo->prepare("
SELECT r.*, s.name_en as supplier_name
FROM pharmacy_purchase_returns r
LEFT JOIN suppliers s ON r.supplier_id = s.id
ORDER BY r.return_date DESC
LIMIT :limit OFFSET :offset
");
$stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
$stmt->execute();
echo json_encode([
'data' => $stmt->fetchAll(PDO::FETCH_ASSOC),
'total' => $total,
'page' => $page,
'limit' => $limit,
'pages' => ceil($total / $limit)
]);
} elseif ($action === 'get_return_details') {
$id = $_GET['id'] ?? 0;
$stmt = $pdo->prepare("
SELECT i.*, d.name_en as drug_name, d.sku, b.batch_number
FROM pharmacy_purchase_return_items i
LEFT JOIN drugs d ON i.drug_id = d.id
LEFT JOIN pharmacy_batches b ON i.batch_id = b.id
WHERE i.return_id = ?
");
$stmt->execute([$id]);
echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC));
} elseif ($action === 'get_supplier_batches') {
// Get batches for a specific supplier (or all if not specified, but usually filtered by drug)
// Ideally: We select a supplier for return, then we select items.
// Better: Select Drug -> Show Batches (maybe filter by supplier if we track supplier_id in batch)
$drug_id = $_GET['drug_id'] ?? 0;
$supplier_id = $_GET['supplier_id'] ?? 0;
$sql = "SELECT b.id, b.batch_number, b.expiry_date, b.quantity, b.cost_price
FROM pharmacy_batches b
WHERE b.drug_id = ? AND b.quantity > 0";
$params = [$drug_id];
if ($supplier_id) {
// If we want to strictly return only what we bought from this supplier:
// $sql .= " AND b.supplier_id = ?";
// $params[] = $supplier_id;
// BUT, sometimes we might return to a supplier what we bought elsewhere if they accept it,
// or `supplier_id` in batches might be null for old data.
// Let's NOT strictly enforce supplier_id match for now, just show all batches.
}
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC));
}
}
} catch (Exception $e) {
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}