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()]); }